summaryrefslogtreecommitdiffstats
path: root/src/build/linker/linker.C
diff options
context:
space:
mode:
authordgilbert <dgilbert@us.ibm.com>2011-07-11 12:05:09 -0500
committerDouglas R. Gilbert <dgilbert@us.ibm.com>2011-07-15 09:58:02 -0500
commit1291feb17fa04747795bf5cff72599fa3733d45f (patch)
tree9e6ae90799074a882fa2e5ec2d52bd1520a7a6a8 /src/build/linker/linker.C
parent353cc0391b0982b936fe0437fbaa0439f775a6dd (diff)
downloadtalos-hostboot-1291feb17fa04747795bf5cff72599fa3733d45f.tar.gz
talos-hostboot-1291feb17fa04747795bf5cff72599fa3733d45f.zip
Linker support for extended image
Change-Id: I21acf1b870667aa3aa2617837bead3a1697db7c1 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/194 Tested-by: Jenkins Server Reviewed-by: Douglas R. Gilbert <dgilbert@us.ibm.com>
Diffstat (limited to 'src/build/linker/linker.C')
-rw-r--r--src/build/linker/linker.C1230
1 files changed, 798 insertions, 432 deletions
diff --git a/src/build/linker/linker.C b/src/build/linker/linker.C
index e7c7aa622..1b414608f 100644
--- a/src/build/linker/linker.C
+++ b/src/build/linker/linker.C
@@ -1,6 +1,15 @@
+/**
+ * @file linker.C Linker to generate the host boot binary images
+ */
+// This code has been extended to create the host boot extended binary image.
+// Most of this code was already in existance and no attempt has been made to make it
+// completely conformant to PFD coding guidelines.
+//
#include <stdint.h>
+#include <stdlib.h>
#include <bfd.h>
#include <iostream>
+#include <iomanip>
#include <fstream>
#include <string>
#include <vector>
@@ -11,12 +20,15 @@
#include <assert.h>
#include <stdlib.h>
#include <algorithm>
+#include <stdexcept>
+#include <sstream>
#include "../../include/sys/vfs.h"
using std::cout;
using std::cerr;
using std::endl;
+using std::setw;
using std::string;
using std::vector;
using std::map;
@@ -24,7 +36,13 @@ using std::for_each;
using std::mem_fun_ref;
using std::bind1st;
using std::ofstream;
+using std::invalid_argument;
+using std::range_error;
+using std::ostringstream;
+/**
+ * Symbol - ELF Symbol information
+ */
struct Symbol
{
string name;
@@ -35,265 +53,461 @@ struct Symbol
enum SymbolType
{
- LOCAL = 0x01,
- GLOBAL = 0x02,
+ LOCAL = 0x01,
+ GLOBAL = 0x02,
- UNRESOLVED = 0x04,
+ UNRESOLVED = 0x04,
- FUNCTION = 0x08,
- VARIABLE = 0x10,
+ FUNCTION = 0x08,
+ VARIABLE = 0x10,
- RELATIVE = 0x20,
+ RELATIVE = 0x20,
};
};
+/**
+ * ELF section
+ */
struct Section
{
string name;
size_t vma_offset;
size_t size;
-
+
bfd_byte* data;
};
+/**
+ * Object ELF image contents or binary blob
+ */
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();
+ string name; //!< full path name of file
+ bfd* image; //!< bfd image of object
+ Section text; //!< text section of binary
+ Section data; //!< data section of binary
+ map<string, Symbol> symbols; //!< symbol map
+ vector<Symbol> relocs; //!< relocations
+ unsigned long offset; //!< output file offset of image start
+ unsigned long base_addr; //!< output file base address
+ FILE * iv_output; //!< output file handle
+
+ /**
+ * Read the object from it's file and extract bfd, text, & data image
+ * @param[in] i_file : file path
+ * @return true if no errors
+ * @post sets name, image, text, data
+ */
+ bool read_object(const char* i_file);
+
+ /**
+ * Write object to iv_output
+ * @return true if no errors
+ * @post sets offset
+ */
+ bool write_object();
+
+ /**
+ * Read relocations
+ * @return true if no errors
+ * @post sets symbols, relocs
+ */
+ bool read_relocation();
+
+
+ /**
+ * Perform local relcations on object
+ * @returns true if no errors
+ */
+ bool perform_local_relocations();
+
+ /**
+ * Perform global relocations
+ * @return tre if no errors
+ */
+ bool perform_global_relocations();
+
+ /**
+ * Query if the object is valid bfd object
+ * @return true if valid bfd object, false if binary blob
+ */
+ bool isELF();
+
+ /**
+ * Find the location of the _init symbol
+ * @return location of the _init symbol
+ */
+ uint64_t find_init_symbol();
+
+ /**
+ * Find the location of the _start symbol
+ * @return location of the _start symbol
+ */
+ uint64_t find_start_symbol();
+
+ /**
+ * Find the location of the _fini symbol
+ * @return location of the _fini symbol
+ */
+ uint64_t find_fini_symbol();
+
+ /**
+ * CTOR default
+ */
+ Object() : image(NULL), offset(0), base_addr(0), iv_output(NULL) {}
+
+ /**
+ * CTOR
+ * @param[in] i_baseAddress of the output binary this object belongs to
+ * @param[in] i_out : output FILE handle
+ */
+ Object(unsigned long i_baseAddr, FILE* i_out)
+ : image(NULL), offset(0), base_addr(i_baseAddr), iv_output(i_out) {}
};
-vector<Object> objects;
-FILE* output;
-ofstream modinfo;
-vector<uint64_t> all_relocations;
+inline bool Object::isELF()
+{
+ return image != NULL;
+}
-int main(int argc, char** argv)
+/**
+ * Infomraiton needed to build the Module table in each output image
+ */
+class ModuleTable
{
- 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;
- }
- // Open modinfo file.
- modinfo.open((string(argv[1])+".modinfo").c_str());
-
- // 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;
- }
- }
+ private:
+ FILE * iv_output;
+ string iv_vfs_mod_table_name;
+
+ public:
+
+ /**
+ * CTOR
+ */
+ ModuleTable(FILE * i_binfile, const string & i_mod_table_name)
+ : iv_output(i_binfile), iv_vfs_mod_table_name(i_mod_table_name) {}
+
+ /**
+ * Write module table to file
+ * @param[in] list of objects
+ */
+ void write_table(vector<Object> & i_objects);
+};
- for_each(objects.begin(), objects.end(),
- bind2nd(mem_fun_ref(&Object::write_object), output));
- uint64_t last_address = ftell(output);
- if (0 != (last_address % 8))
+/**
+ * Align offset to 4k page boundary
+ * @param[in] i_offset value to align
+ * @returns page aligned value
+ */
+inline uint64_t page_align(uint64_t i_offset)
+{
+ uint32_t v = i_offset;
+ if(i_offset % 4096)
+ v = i_offset + (4096 - i_offset % 4096);
+ return v;
+}
+
+/**
+ * Align file ptr to 4k page boundary
+ * @param i_f FILE *
+ */
+inline void advance_to_page_align(FILE * i_f)
+{
+ long pos = ftell(i_f);
+ if( pos % 4096 )
{
- char zero = 0;
- fwrite(&zero, 0, 8 - (last_address % 8), output);
- last_address = ftell(output);
+ fseek(i_f, 4096 - (pos % 4096), SEEK_CUR);
}
+}
- 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;
+//
+// Global variables
+//
+vector<Object> objects;
+ofstream modinfo;
+vector<uint64_t> all_relocations;
+vector<ModuleTable> module_tables;
- fseek(output, module_table_address, SEEK_SET);
+//-----------------------------------------------------------------------------
+// MAIN
+//-----------------------------------------------------------------------------
+int main(int argc, char** argv)
+{
+ int rc = 0;
+ FILE * output;
+ bool isOutput = true;
+ unsigned long base_addr = 0;
- if ((objects.size()-1) > VFS_MODULE_MAX)
+ if (argc <= 2)
{
- cout << "Error: Too many modules." << endl;
- return -1;
+ cout << argv[0] << " <output> <kernel> <modules>"
+ " [--extended=<page_addr> <output> <modules>]" << endl;
+ return -1;
}
-
- cout << "Updating module table... " << endl;
- for (vector<Object>::iterator i = ++objects.begin();
- i != objects.end();
- ++i)
+
+ try
{
- 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)];
-
- if (0 != init_symbol)
- all_relocations.push_back(ftell(output));
- bfd_putb64(init_symbol, data);
- fwrite(data, sizeof(uint64_t), 1, output);
- if (0 != start_symbol)
- all_relocations.push_back(ftell(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;
+ // Open modinfo file.
+ modinfo.open((string(argv[1])+".modinfo").c_str());
+
+ // Read input args - generate objects.
+ for (int files = 1; files < argc; files++)
+ {
+ string fname(argv[files]);
+ if(isOutput)
+ {
+ isOutput = false;
+ output = fopen(fname.c_str(), "w+");
+ if (NULL == output)
+ {
+ int error = errno;
+ ostringstream oss;
+ oss << "Error opening " << fname << endl;
+ oss << strerror(error);
+ cout << oss.str() << endl;
+ throw invalid_argument(oss.str());
+ }
+ string table_symbol;
+ if(base_addr == 0)
+ {
+ table_symbol = VFS_TOSTRING(VFS_MODULES);
+ }
+ else // extended module
+ {
+ // allocate space for the module table in the extended image
+ uint64_t table_size =
+ page_align(112*VFS_EXTENDED_MODULE_MAX);
+ fseek(output, table_size, SEEK_SET);
+ }
+ ModuleTable module_table(output,table_symbol);
+ module_tables.push_back(module_table);
+ }
+ else if (0 == fname.compare(0,11,"--extended="))
+ {
+ base_addr = strtoul(fname.c_str()+11,NULL,16) * 0x1000;
+ isOutput = true;
+ }
+ else
+ {
+ Object o(base_addr,output);
+ if(access(fname.c_str(),F_OK) != 0)
+ {
+ ostringstream oss;
+ oss << "Error! File " << fname << " does not exist";
+ cout << oss.str() << endl;
+ throw invalid_argument(oss.str());
+ }
+ else if (o.read_object(fname.c_str()))
+ {
+ if(o.isELF())
+ {
+ o.read_relocation();
+ }
+ objects.push_back(o);
+ cout << endl;
+ }
+ }
+ }
+
+ // Write objects to their output file
+ for_each(objects.begin(), objects.end(),
+ mem_fun_ref(&Object::write_object));
+ //bind2nd(mem_fun_ref(&Object::write_object), output));
+
+ // used to find start of unallocated memory
+ // goes in base binary only
+ uint64_t last_address = ftell(objects[0].iv_output);
+
+ cout << "Local relocations..." << endl;
+ for_each(objects.begin(), objects.end(),
+ mem_fun_ref(&Object::perform_local_relocations));
+ //bind2nd(mem_fun_ref(&Object::perform_local_relocations), output));
+ cout << endl;
+
+ cout << "Global relocations..." << endl;
+ for_each(objects.begin(), objects.end(),
+ mem_fun_ref(&Object::perform_global_relocations));
+ //bind2nd(mem_fun_ref(&Object::perform_global_relocations), output));
+ cout << endl;
+
+
+ //
+ // Create module tables
+ //
+ for(vector<ModuleTable>::iterator i = module_tables.begin();
+ i != module_tables.end(); ++i)
+ {
+ i->write_table(objects);
+ }
+
+ //
+ // Last Address
+ // Only appies to base binary file
+ //
+
+ 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(objects[0].iv_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, objects[0].iv_output);
+
+ cout << last_address << " to " << last_address_entry_address << endl;
+
+ // Output relocation data.
+ {
+ fseek(objects[0].iv_output, 0, SEEK_END);
+ char temp64[sizeof(uint64_t)];
+
+ uint64_t count = all_relocations.size();
+ bfd_putb64(count, temp64);
+ fwrite(temp64, sizeof(uint64_t), 1, objects[0].iv_output);
+
+ for (int i = 0; i < all_relocations.size(); i++)
+ {
+ bfd_putb64(all_relocations[i], temp64);
+ fwrite(temp64, sizeof(uint64_t), 1, objects[0].iv_output);
+ }
+ }
}
-
- 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;
-
- // Output relocation data.
+ catch (std::exception & e)
{
- fseek(output, 0, SEEK_END);
- char temp64[sizeof(uint64_t)];
-
- uint64_t count = all_relocations.size();
- bfd_putb64(count, temp64);
- fwrite(temp64, sizeof(uint64_t), 1, output);
-
- for (int i = 0; i < all_relocations.size(); i++)
- {
- bfd_putb64(all_relocations[i], temp64);
- fwrite(temp64, sizeof(uint64_t), 1, output);
- }
+ cerr << "exception caught: " << e.what() << endl;
+ rc = -1;
}
- return 0;
+ return rc;
}
-bool Object::read_object(char* file)
+//-----------------------------------------------------------------------------
+
+bool Object::read_object(const char* i_file)
{
+ name = i_file;
+ cout << "File " << i_file << endl;
+ bool result = true;
+
// Open BFD file.
- image = bfd_openr(file, NULL);
+ image = bfd_openr(i_file, NULL);
if (!bfd_check_format(image, bfd_object))
{
- cout << "Unsupported file format: " << file << endl;
- return false;
+ // Tread file as a binar blob
+ if(!bfd_close(image))
+ {
+ cout << "ERROR: Unexpected error closing file " << i_file << endl;
+ result = false;
+ }
+ else
+ {
+ cout << "NON ELF format on file: " << i_file
+ << ". The file will be added as a binary blob." << endl;
+ image = NULL;
+ }
}
-
- name = file;
- cout << "File " << file << endl;
-
- // Read sections.
- bfd_section* image_section = image->sections;
- while(image_section != NULL)
+ else // BFD file
{
- 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;
+
+ // 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;
+ return result;
}
-#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)
+//-----------------------------------------------------------------------------
+
+bool Object::write_object()
{
// 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;
+ advance_to_page_align(iv_output);
+ offset = ftell(iv_output);
+
+ if(isELF())
+ {
+ // Output TEXT section.
+ fseek(iv_output, text.vma_offset, SEEK_CUR);
+ if (text.size != fwrite(text.data, 1, text.size, iv_output))
+ {
+ int error = errno;
+ cout << "Error writing to output." << endl;
+ cout << strerror(error) << endl;
+ }
+
+ // Output DATA section.
+ fseek(iv_output, offset + data.vma_offset, SEEK_SET);
+ if (data.size != fwrite(data.data, 1, data.size, iv_output))
+ {
+ int error = errno;
+ cout << "Error writing to output." << endl;
+ cout << strerror(error) << endl;
+ }
+
+ // make file end on 8 byte boundary
+ uint64_t eof = ftell(iv_output);
+ if (0 != (eof % 8))
+ {
+ char zero = 0;
+ fwrite(&zero, 0, 8 - (eof % 8), iv_output);
+ }
+
+ modinfo << &name[(name.find_last_of("/")+1)] << ",0x"
+ << std::hex << offset + base_addr << endl;
}
-
- // Output DATA section.
- fseek(file, offset + data.vma_offset, SEEK_SET);
- if (data.size != fwrite(data.data, 1, data.size, file))
+ else // binary blob
{
- int error = errno;
- cout << "Error writing to output." << endl;
- cout << strerror(error) << endl;
+ FILE * file = fopen(name.c_str(),"rb");
+ fseek(file,0,SEEK_END);
+ long int file_size = ftell(file);
+ uint8_t * buffer = new uint8_t[file_size];
+ fseek(file,0,SEEK_SET);
+ fread(buffer,file_size,1,file);
+ fwrite(buffer,file_size,1,iv_output);
+ delete [] buffer;
+ fclose(file);
}
-
- modinfo << &name[(name.find_last_of("/")+1)] << ",0x" << std::hex << offset << endl;
}
+//-----------------------------------------------------------------------------
+
bool Object::read_relocation()
{
+ if(!isELF()) return false;
+
+ bool result = true;
asymbol** syms = NULL;
long symbols = 0;
arelent** loc = NULL;
@@ -301,292 +515,444 @@ bool Object::read_relocation()
// 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);
- }
+ 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);
- }
+ 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 << "Couldn't find symbol table." << endl;
+ result = false;
+ goto cleanup;
}
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.base = syms[i]->section->vma;
- 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;
+ Symbol s;
+ s.name = syms[i]->name;
+ s.address = syms[i]->value;
+ s.base = syms[i]->section->vma;
+ 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);
- }
+ 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;
+ 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;
- }
-
- if (loc[i]->howto->name == string("R_PPC64_ADDR64"))
- {
- s.type |= Symbol::VARIABLE;
- }
- else if (loc[i]->howto->name == string("R_PPC64_JMP_SLOT"))
- {
- s.type |= Symbol::FUNCTION;
- }
- 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;
+ 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;
+ }
+
+ if (loc[i]->howto->name == string("R_PPC64_ADDR64"))
+ {
+ s.type |= Symbol::VARIABLE;
+ }
+ else if (loc[i]->howto->name == string("R_PPC64_JMP_SLOT"))
+ {
+ s.type |= Symbol::FUNCTION;
+ }
+ 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);
+ free(loc);
if (NULL != syms)
- free(syms);
+ free(syms);
- return true;
+ return result;
}
-bool Object::perform_local_relocations(FILE* file)
+//-----------------------------------------------------------------------------
+
+bool Object::perform_local_relocations()
{
cout << "File " << name << endl;
for(vector<Symbol>::iterator i = relocs.begin();
i != relocs.end();
- ++i)
+ ++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
- << " at " << (offset + i->address) << endl;
- cerr << "Expected " << i->addend << " found " << address
- << " at " << (offset + i->address) << endl;
- exit(-1);
- }
-
- // If it is a non-ABS relocation, also need to add the symbol addr.
- if (i->name != BFD_ABS_SECTION_NAME)
- {
- Symbol& s = this->symbols[i->name];
- uint64_t symbol_addr = s.base + s.address;
- i->addend += symbol_addr;
- relocation += symbol_addr;
- }
-
- address = relocation;
- bfd_putb64(address, data);
- all_relocations.push_back(offset + i->address);
-
- fseek(file, offset + i->address, SEEK_SET);
- fwrite(data, sizeof(uint64_t), 1, file);
-
- cout << "\tRelocated " << i->addend << " at " << i->address << " to "
- << relocation << endl;
+ 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(iv_output, offset + i->address, SEEK_SET);
+ fread(data, sizeof(uint64_t), 1, iv_output);
+
+ address = bfd_getb64(data);
+ if (address != i->addend)
+ {
+ ostringstream oss;
+ oss << "Expected " << i->addend << " found " << address
+ << " at " << (offset + i->address);
+ cout << oss.str() << endl;
+ throw range_error(oss.str());
+ }
+
+ // If it is a non-ABS relocation, also need to add the symbol addr.
+ if (i->name != BFD_ABS_SECTION_NAME)
+ {
+ Symbol& s = this->symbols[i->name];
+ uint64_t symbol_addr = s.base + s.address;
+ i->addend += symbol_addr;
+ relocation += symbol_addr;
+ }
+
+ address = relocation + base_addr; //dgxxa
+ bfd_putb64(address, data);
+ if(!base_addr) all_relocations.push_back(offset + i->address);
+
+ fseek(iv_output, offset + i->address, SEEK_SET);
+ fwrite(data, sizeof(uint64_t), 1, iv_output);
+
+ cout << "\tRelocated " << i->addend << " at " << i->address << " to "
+ << relocation << endl;
}
}
-bool Object::perform_global_relocations(FILE* file)
+//-----------------------------------------------------------------------------
+
+bool Object::perform_global_relocations()
{
cout << "File " << name << endl;
for(vector<Symbol>::iterator i = relocs.begin();
i != relocs.end();
- ++i)
+ ++i)
{
- bool found_symbol = false;
-
- if (!(i->type & Symbol::UNRESOLVED))
- continue;
-
- cout << "\tSymbol: " << i->name << endl;
-
- char data[sizeof(uint64_t)*3];
-
- for(int allow_local = 0;
- ((allow_local < 2) && (!found_symbol));
- allow_local++)
- {
- 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 + s.base;
-
- if (s.type & Symbol::UNRESOLVED)
- continue;
- if ((s.type & Symbol::LOCAL) && (!allow_local))
- continue;
- if ((!(s.type & Symbol::GLOBAL)) && (!allow_local))
- continue;
-
- found_symbol = true;
-
- if ((s.type & Symbol::FUNCTION) &&
- (i->type & Symbol::FUNCTION))
- {
- if (i->addend != 0)
- {
- cerr << "Can't handle offset unresolved function."
- << endl;
- exit(-1);
- }
-
- 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);
- all_relocations.push_back(offset + i->address);
- all_relocations.push_back(offset + i->address + 8);
- all_relocations.push_back(offset + i->address + 16);
-
- cout << "\tCopied relocation from " << std::hex
- << symbol_addr << " to "
- << offset + i->address << "." << endl;
- }
- else
- {
- if (s.type & Symbol::FUNCTION)
- {
- cout << "\tTOC link for function: " << s.name
- << endl;
- }
- if (i->addend != 0)
- {
- cout << "\tOffset to " << i->addend << endl;
- symbol_addr += i->addend;
- }
- bfd_putb64(symbol_addr, data);
- fseek(file, offset + i->address, SEEK_SET);
- fwrite(data, sizeof(uint64_t), 1, file);
- all_relocations.push_back(offset + i->address);
-
- cout << "\tRelocated from " << std::hex
- << symbol_addr << " to "
- << offset + i->address << "." << endl;
- }
- break;
- }
- }
- }
-
- if (!found_symbol)
- {
- cout << "Could not find symbol " << i->name << std::endl;
- cerr << "Could not find symbol " << i->name << std::endl;
- exit(-1);
- }
+ bool found_symbol = false;
+
+ if (!(i->type & Symbol::UNRESOLVED))
+ continue;
+
+ cout << "\tSymbol: " << i->name << endl;
+
+ char data[sizeof(uint64_t)*3];
+
+ for(int allow_local = 0;
+ ((allow_local < 2) && (!found_symbol));
+ allow_local++)
+ {
+ 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 + s.base;
+
+ if (s.type & Symbol::UNRESOLVED)
+ continue;
+ if ((s.type & Symbol::LOCAL) && (!allow_local))
+ continue;
+ if ((!(s.type & Symbol::GLOBAL)) && (!allow_local))
+ continue;
+
+ found_symbol = true;
+
+ if ((s.type & Symbol::FUNCTION) &&
+ (i->type & Symbol::FUNCTION))
+ {
+ if (i->addend != 0)
+ {
+ ostringstream oss;
+ oss << "Can't handle offset unresolved function."
+ << " Symbol: " << s.name;
+ cout << oss.str() << endl;
+ throw range_error(oss.str());
+ }
+
+ fseek(j->iv_output, symbol_addr, SEEK_SET);
+ fread(data, sizeof(uint64_t), 3, j->iv_output);
+
+ fseek(iv_output, offset + i->address, SEEK_SET);
+ fwrite(data, sizeof(uint64_t), 3, iv_output);
+ if(!base_addr)
+ {
+ all_relocations.push_back(offset + i->address);
+ all_relocations.push_back(offset + i->address + 8);
+ all_relocations.push_back(offset + i->address + 16);
+ }
+
+ cout << "\tCopied relocation from " << std::hex
+ << j->base_addr << ':' << symbol_addr << " to "
+ << base_addr << ':' << offset + i->address << "."
+ << endl;
+ }
+ else
+ {
+ if (s.type & Symbol::FUNCTION)
+ {
+ cout << "\tTOC link for function: " << s.name
+ << endl;
+ }
+ if (i->addend != 0)
+ {
+ cout << "\tOffset to " << i->addend << endl;
+ symbol_addr += i->addend;
+ }
+ symbol_addr += j->base_addr;
+ bfd_putb64(symbol_addr, data);
+ fseek(iv_output, offset + i->address, SEEK_SET);
+ fwrite(data, sizeof(uint64_t), 1, iv_output);
+ if(!base_addr) all_relocations.push_back(offset + i->address);
+
+ cout << "\tRelocated from " << std::hex
+ << j->base_addr << ':'
+ << symbol_addr - j->base_addr << " to "
+ << base_addr << ':' << offset + i->address << "."
+ << endl;
+ }
+ break;
+ }
+ }
+ }
+
+ if (!found_symbol)
+ {
+ ostringstream oss;
+ oss << "Could not find symbol " << i->name;
+ cout << oss.str() << endl;
+ throw range_error(oss.str());
+ }
}
}
+//-----------------------------------------------------------------------------
+
uint64_t Object::find_init_symbol()
{
if (symbols.find(VFS_TOSTRING(VFS_SYMBOL_INIT)) == symbols.end())
- return 0;
+ return 0;
return symbols[VFS_TOSTRING(VFS_SYMBOL_INIT)].address +
- offset + data.vma_offset;
+ offset + base_addr + data.vma_offset;
}
+//-----------------------------------------------------------------------------
+
uint64_t Object::find_start_symbol()
{
if (symbols.find(VFS_TOSTRING(VFS_SYMBOL_START)) == symbols.end())
- return 0;
+ return 0;
return symbols[VFS_TOSTRING(VFS_SYMBOL_START)].address +
- offset + data.vma_offset;
+ offset + base_addr + data.vma_offset;
+}
+
+//-----------------------------------------------------------------------------
+
+uint64_t Object::find_fini_symbol()
+{
+ if (symbols.find(VFS_TOSTRING(VFS_SYMBOL_FINI)) == symbols.end())
+ return 0;
+
+ return symbols[VFS_TOSTRING(VFS_SYMBOL_FINI)].address +
+ offset + base_addr + data.vma_offset;
+}
+
+
+//-----------------------------------------------------------------------------
+
+void ModuleTable::write_table(vector<Object> & i_objects)
+{
+ vector<Object>::iterator i = i_objects.begin();
+
+ uint64_t module_table_offset = 0;
+ uint64_t module_count = 0;
+ uint64_t max_modules = 0;
+
+ if (iv_vfs_mod_table_name.size() != 0)
+ {
+ // Base module - First object is elf image, find the table location
+ module_table_offset =
+ i->symbols[iv_vfs_mod_table_name].address +
+ i->offset + i->data.vma_offset;
+
+ cout << "Updating base module table..." << endl;
+ max_modules = VFS_MODULE_MAX;
+ ++i;
+ }
+ else
+ {
+ // Extended module - module table is at offset 0 in file
+ cout << "Updating extended module table..." << endl;
+ max_modules = VFS_EXTENDED_MODULE_MAX;
+ }
+
+ fseek(iv_output, module_table_offset, SEEK_SET);
+
+ for(; i != i_objects.end(); ++i)
+ {
+ if(i->iv_output != this->iv_output) continue;
+
+ ++module_count;
+ if(module_count > max_modules)
+ {
+ ostringstream oss;
+ oss << "Too many modules. Max = " << max_modules;
+ cout << oss.str() << endl;
+ throw range_error(oss.str());
+ }
+ 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, iv_output);
+
+ uint64_t init_symbol = 0;
+ uint64_t start_symbol = 0;
+ uint64_t fini_symbol = 0;
+ uint64_t text_offset = 0;
+ uint64_t data_offset = 0;
+ uint64_t module_size = 0;
+
+ if(i->isELF())
+ {
+ init_symbol = i->find_init_symbol();
+ start_symbol = i->find_start_symbol();
+ fini_symbol = i->find_fini_symbol();
+ text_offset = i->text.vma_offset + i->offset + i->base_addr;
+ data_offset = i->data.vma_offset + i->offset + i->base_addr;
+ module_size = i->data.vma_offset + i->data.size;
+ }
+ else // binary blob
+ {
+ FILE * f = fopen(i->name.c_str(), "rb"); // file has to exist already
+ fseek(f,0,SEEK_END);
+ module_size = ftell(f);
+ text_offset = data_offset = i->offset + i->base_addr;
+ fclose(f);
+ }
+
+ module_size = page_align(module_size)/4096;
+
+ char data[sizeof(uint64_t)];
+
+ if (0 != init_symbol && !i->base_addr)
+ all_relocations.push_back(ftell(iv_output));
+ bfd_putb64(init_symbol, data);
+ fwrite(data, sizeof(uint64_t), 1, iv_output);
+
+ if (0 != start_symbol && !i->base_addr)
+ all_relocations.push_back(ftell(iv_output));
+ bfd_putb64(start_symbol, data);
+ fwrite(data, sizeof(uint64_t), 1, iv_output);
+
+ if (0 != fini_symbol && !i->base_addr)
+ all_relocations.push_back(ftell(iv_output));
+ bfd_putb64(fini_symbol, data);
+ fwrite(data, sizeof(uint64_t), 1, iv_output);
+
+ if (0 != text_offset && !i->base_addr)
+ all_relocations.push_back(ftell(iv_output));
+ bfd_putb64(text_offset, data);
+ fwrite(data, sizeof(uint64_t), 1, iv_output);
+
+ if (0 != data_offset && !i->base_addr)
+ all_relocations.push_back(ftell(iv_output));
+ bfd_putb64(data_offset, data);
+ fwrite(data, sizeof(uint64_t), 1, iv_output);
+
+ if(!i->base_addr)
+ all_relocations.push_back(ftell(iv_output));
+ bfd_putb64(module_size, data);
+ fwrite(data, sizeof(uint64_t), 1, iv_output);
+
+ cout << std::hex << std::setfill('0');
+ cout << "\tAdded module " << object_name
+ << " page size 0x" << module_size << endl;
+ cout << "\t\twith .text at 0x" << setw(16) << text_offset << endl;
+ cout << "\t\twith .data at 0x" << setw(16) << data_offset << endl;
+ cout << "\t\twith init at 0x" << setw(16) << init_symbol << endl;
+ cout << "\t\twith start at 0x" << setw(16) << start_symbol << endl;
+ cout << "\t\twith fini at 0x" << setw(16) << fini_symbol << endl;
+ }
}
+
OpenPOWER on IntegriCloud