diff options
author | Patrick Williams <iawillia@us.ibm.com> | 2010-10-05 17:36:28 -0500 |
---|---|---|
committer | Patrick Williams <iawillia@us.ibm.com> | 2010-10-05 17:36:28 -0500 |
commit | 9fb915bfdc1165bd645c25619623c677b00432b4 (patch) | |
tree | 9c5677983611f2ab63a4f973536e82d0a505e204 | |
parent | 5d43599264f23482f84fbd82958ce60fac43c4b4 (diff) | |
download | talos-hostboot-9fb915bfdc1165bd645c25619623c677b00432b4.tar.gz talos-hostboot-9fb915bfdc1165bd645c25619623c677b00432b4.zip |
Missed deleting original linker when moving.
-rw-r--r-- | src/build/linker.C | 495 |
1 files changed, 0 insertions, 495 deletions
diff --git a/src/build/linker.C b/src/build/linker.C deleted file mode 100644 index fda2059d4..000000000 --- a/src/build/linker.C +++ /dev/null @@ -1,495 +0,0 @@ -#include <stdint.h> -#include <bfd.h> -#include <iostream> -#include <string> -#include <vector> -#include <map> -#include <stdio.h> -#include <errno.h> -#include <string.h> -#include <assert.h> -#include <stdlib.h> -#include <algorithm> - -#include <vfs.h> - -using std::cout; -using std::endl; -using std::string; -using std::vector; -using std::map; -using std::for_each; -using std::mem_fun_ref; -using std::bind1st; - -struct Symbol -{ - string name; - uint8_t type; - uint64_t address; - uint64_t addend; - - enum SymbolType - { - LOCAL = 0x01, - GLOBAL = 0x02, - - UNRESOLVED = 0x04, - - FUNCTION = 0x08, - VARIABLE = 0x10, - - RELATIVE = 0x20, - }; -}; - -struct Section -{ - string name; - size_t vma_offset; - size_t size; - - bfd_byte* data; -}; - -struct Object -{ - public: - string name; - bfd* image; - Section text; - Section data; - map<string, Symbol> symbols; - vector<Symbol> relocs; - long offset; - - bool read_object(char* file); - bool write_object(FILE* file); - bool read_relocation(); - bool perform_local_relocations(FILE* file); - bool perform_global_relocations(FILE* file); - - uint64_t find_init_symbol(); - uint64_t find_start_symbol(); -}; - -vector<Object> objects; -FILE* output; - -int main(int argc, char** argv) -{ - if (argc <= 2) - { - cout << argv[0] << " <output> <kernel> <modules>" << endl; - return -1; - } - - // Open output file. - output = fopen(argv[1], "w+"); - if (NULL == output) - { - int error = errno; - cout << "Error opening " << argv[1] << endl; - cout << strerror(error) << endl; - } - - // Read input objects. - for (int files = 2; files < argc; files++) - { - Object o; - if (o.read_object(argv[files])) - { - o.read_relocation(); - objects.push_back(o); - cout << endl; - } - } - - for_each(objects.begin(), objects.end(), - bind2nd(mem_fun_ref(&Object::write_object), output)); - uint64_t last_address = ftell(output); - - cout << "Local relocations..." << endl; - for_each(objects.begin(), objects.end(), - bind2nd(mem_fun_ref(&Object::perform_local_relocations), output)); - cout << endl; - - cout << "Global relocations..." << endl; - for_each(objects.begin(), objects.end(), - bind2nd(mem_fun_ref(&Object::perform_global_relocations), output)); - cout << endl; - - // Create module table. - uint64_t module_table_address = - objects[0].symbols[VFS_TOSTRING(VFS_MODULES)].address + - objects[0].offset + objects[0].data.vma_offset; - - fseek(output, module_table_address, SEEK_SET); - - if ((objects.size()-1) > VFS_MODULE_MAX) - { - cout << "Error: Too many modules." << endl; - return -1; - } - - cout << "Updating module table... " << endl; - for (vector<Object>::iterator i = ++objects.begin(); - i != objects.end(); - ++i) - { - string object_name = i->name; - object_name.erase(0, object_name.find_last_of("/")+1); - - char obj_name[VFS_MODULE_NAME_MAX]; - memset(obj_name, '\0', VFS_MODULE_NAME_MAX); - strncpy(obj_name, object_name.c_str(), VFS_MODULE_NAME_MAX-1); - fwrite(obj_name, VFS_MODULE_NAME_MAX, 1, output); - - uint64_t init_symbol = i->find_init_symbol(); - uint64_t start_symbol = i->find_start_symbol(); - - char data[sizeof(uint64_t)]; - - bfd_putb64(init_symbol, data); - fwrite(data, sizeof(uint64_t), 1, output); - bfd_putb64(start_symbol, data); - fwrite(data, sizeof(uint64_t), 1, output); - - cout << "\tAdded module " << object_name << " with init at " - << std::hex << init_symbol << " and start at " - << start_symbol << endl; - } - - cout << "Updating last address..." << std::hex; - uint64_t last_address_entry_address = - objects[0].symbols[VFS_TOSTRING(VFS_LAST_ADDRESS)].address + - objects[0].offset + objects[0].data.vma_offset; - - fseek(output, last_address_entry_address, SEEK_SET); - char last_addr_data[sizeof(uint64_t)]; - bfd_putb64(last_address, last_addr_data); - fwrite(last_addr_data, sizeof(uint64_t), 1, output); - - cout << last_address << " to " << last_address_entry_address << endl; - - return 0; -} - -bool Object::read_object(char* file) -{ - // Open BFD file. - image = bfd_openr(file, NULL); - if (!bfd_check_format(image, bfd_object)) - { - cout << "Unsupported file format: " << file << endl; - return false; - } - - name = file; - cout << "File " << file << endl; - - // Read sections. - bfd_section* image_section = image->sections; - while(image_section != NULL) - { - Section* s = NULL; - if (string(".text") == bfd_get_section_name(image, image_section)) - { - s = &this->text; - } - if (string(".data") == bfd_get_section_name(image, image_section)) - { - s = &this->data; - } - if (NULL != s) - { - s->name = bfd_get_section_name(image, image_section); - s->vma_offset = bfd_get_section_vma(image, image_section); - s->size = bfd_get_section_size(image_section); - - bfd_malloc_and_get_section(image, image_section, &s->data); - - cout << "Section " << s->name << endl; - cout << "\tSize " << std::dec << s->size << endl; - cout << "\tVMA " << std::hex << s->vma_offset << endl; - cout << "\tData " << std::hex << bfd_getb64(s->data) - << "..." << endl; - } - - image_section = image_section->next; - } - - return true; -} - -#define advance_to_page_align(f) \ - { \ - long pos = ftell(f); \ - if (pos % 4096) \ - { \ - fseek((f), 4096 - (pos % 4096), SEEK_CUR); \ - } \ - } - -bool Object::write_object(FILE* file) -{ - // Start outputing object at page boundary. - advance_to_page_align(file); - offset = ftell(file); - - // Output TEXT section. - fseek(file, text.vma_offset, SEEK_CUR); - if (text.size != fwrite(text.data, 1, text.size, file)) - { - int error = errno; - cout << "Error writing to output." << endl; - cout << strerror(error) << endl; - } - - // Output DATA section. - fseek(file, offset + data.vma_offset, SEEK_SET); - if (data.size != fwrite(data.data, 1, data.size, file)) - { - int error = errno; - cout << "Error writing to output." << endl; - cout << strerror(error) << endl; - } -} - -bool Object::read_relocation() -{ - asymbol** syms = NULL; - long symbols = 0; - arelent** loc = NULL; - long locs = 0; - - // Read symbol tables. - { - long symbol_size = bfd_get_dynamic_symtab_upper_bound(image); - if (0 < symbol_size) - { - syms = (asymbol**) malloc(symbol_size); - symbols = bfd_canonicalize_dynamic_symtab(image, syms); - } - } - if (0 >= symbols) - { - long symbol_size = bfd_get_symtab_upper_bound(image); - if (0 < symbol_size) - { - syms = (asymbol**) malloc(symbol_size); - symbols = bfd_canonicalize_symtab(image, syms); - } - } - if (0 >= symbols) - { - cout << "Couldn't find symbol table." << endl; - return false; - } - cout << "Symbols: " << std::dec << symbols << endl; - for (int i = 0; i < symbols; i++) - { - Symbol s; - s.name = syms[i]->name; - s.address = syms[i]->value; - s.type = 0; - - cout << "\tSymbol: " << syms[i]->name << endl; - cout << "\t\tAddress: " << std::hex << syms[i]->value << endl; - - // Determine symbol types. - if (syms[i]->flags & BSF_GLOBAL) - { - s.type |= Symbol::GLOBAL; - cout << "\t\tGLOBAL" << endl; - } - else if (syms[i]->flags & (BSF_LOCAL | BSF_WEAK)) - { - s.type |= Symbol::LOCAL; - cout << "\t\tLOCAL" << endl; - } - else - { - s.type |= Symbol::UNRESOLVED; - cout << "\t\tUNDEFINED " << std::hex << syms[i]->flags << endl; - } - - if (syms[i]->flags & BSF_FUNCTION) - { - s.type |= Symbol::FUNCTION; - cout << "\t\tFUNCTION" << endl; - } - else if (!(s.type & Symbol::UNRESOLVED)) - { - s.type |= Symbol::VARIABLE; - cout << "\t\tVARIABLE" << endl; - } - - // Add symbol to table. - if (!(s.type & Symbol::UNRESOLVED)) - this->symbols[s.name] = s; - } - - // Read relocations. - { - long loc_size = bfd_get_dynamic_reloc_upper_bound(image); - if (0 < loc_size) - { - loc = (arelent**) malloc(loc_size); - memset(loc, '\0', loc_size); - locs = bfd_canonicalize_dynamic_reloc(image, loc, syms); - } - } - if (0 >= locs) - { - goto cleanup; - } - - cout << "Relocs: " << std::dec << locs << endl; - for (int i = 0; i < locs; i++) - { - Symbol s; - - s.name = loc[i]->sym_ptr_ptr[0]->name; - s.address = loc[i]->address; - s.addend = loc[i]->addend; - if ((s.name == BFD_ABS_SECTION_NAME) || - (this->symbols.find(s.name) != this->symbols.end())) - { - s.type = Symbol::RELATIVE; - } - else - { - s.type = Symbol::UNRESOLVED; - } - this->relocs.push_back(s); - - cout << "\tSymbol: " << loc[i]->sym_ptr_ptr[0]->name; - cout << "\tAddress: " << std::hex << loc[i]->address << ", " - << loc[i]->addend << endl; - } - -cleanup: - if (NULL != loc) - free(loc); - if (NULL != syms) - free(syms); - - return true; -} - -bool Object::perform_local_relocations(FILE* file) -{ - cout << "File " << name << endl; - - for(vector<Symbol>::iterator i = relocs.begin(); - i != relocs.end(); - ++i) - { - if (i->type & Symbol::UNRESOLVED) - continue; - - cout << "\tSymbol: " << i->name << endl; - - uint64_t relocation = i->addend + offset; - uint64_t address = 0; - char data[sizeof(uint64_t)]; - - fseek(file, offset + i->address, SEEK_SET); - fread(data, sizeof(uint64_t), 1, file); - - address = bfd_getb64(data); - if (address != i->addend) - { - cout << "Expected " << i->addend << " found " << address << endl; - continue; - } - - address = relocation; - bfd_putb64(address, data); - - fseek(file, offset + i->address, SEEK_SET); - fwrite(data, sizeof(uint64_t), 1, file); - - cout << "\tRelocated " << i->addend << " to " - << relocation << endl; - } -} - -bool Object::perform_global_relocations(FILE* file) -{ - cout << "File " << name << endl; - - for(vector<Symbol>::iterator i = relocs.begin(); - i != relocs.end(); - ++i) - { - if (!(i->type & Symbol::UNRESOLVED)) - continue; - - cout << "\tSymbol: " << i->name << endl; - - char data[sizeof(uint64_t)*3]; - - for(vector<Object>::iterator j = objects.begin(); - j != objects.end(); - ++j) - { - if (j->symbols.find(i->name) != j->symbols.end()) - { - Symbol s = j->symbols[i->name]; - uint64_t symbol_addr = - j->offset + s.address + j->data.vma_offset; - - if (s.type & Symbol::UNRESOLVED) - continue; - if (s.type & Symbol::LOCAL) - continue; - if (!(s.type & Symbol::GLOBAL)) - continue; - - if (s.type & Symbol::FUNCTION) - { - fseek(file, symbol_addr, SEEK_SET); - fread(data, sizeof(uint64_t), 3, file); - - fseek(file, offset + i->address, SEEK_SET); - fwrite(data, sizeof(uint64_t), 3, file); - - cout << "\tCopied relocation from " << std::hex - << symbol_addr << " to " - << offset + i->address << "." << endl; - } - else - { - bfd_putb64(symbol_addr, data); - fseek(file, offset + i->address, SEEK_SET); - fwrite(data, sizeof(uint64_t), 1, file); - - cout << "\tRelocated from " << std::hex - << symbol_addr << " to " - << offset + i->address << "." << endl; - } - break; - } - } - } -} - -uint64_t Object::find_init_symbol() -{ - if (symbols.find(VFS_TOSTRING(VFS_SYMBOL_INIT)) == symbols.end()) - return 0; - - return symbols[VFS_TOSTRING(VFS_SYMBOL_INIT)].address + - offset + data.vma_offset; -} - -uint64_t Object::find_start_symbol() -{ - if (symbols.find(VFS_TOSTRING(VFS_SYMBOL_START)) == symbols.end()) - return 0; - - return symbols[VFS_TOSTRING(VFS_SYMBOL_START)].address + - offset + data.vma_offset; -} |