mirror of
https://git.rtems.org/rtems-tools/
synced 2025-06-18 06:45:29 +08:00
Relocation fixes.
These changes implement a suitable relocation output in the image. The code is still not working 100% but these changes are a big improvement.
This commit is contained in:
parent
90d8d43e4b
commit
42f766f0ca
@ -83,14 +83,6 @@ namespace rld
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
|
||||||
relocation::name () const
|
|
||||||
{
|
|
||||||
if (sym)
|
|
||||||
return sym->name ();
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
elf_addr
|
elf_addr
|
||||||
relocation::offset () const
|
relocation::offset () const
|
||||||
{
|
{
|
||||||
@ -115,6 +107,14 @@ namespace rld
|
|||||||
return addend_;
|
return addend_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const symbols::symbol&
|
||||||
|
relocation::symbol () const
|
||||||
|
{
|
||||||
|
if (sym)
|
||||||
|
return *sym;
|
||||||
|
throw rld::error ("no symbol", "elf:relocation");
|
||||||
|
}
|
||||||
|
|
||||||
section::section (file& file_,
|
section::section (file& file_,
|
||||||
int index_,
|
int index_,
|
||||||
const std::string& name_,
|
const std::string& name_,
|
||||||
@ -925,6 +925,12 @@ namespace rld
|
|||||||
<< " addend:" << erela.r_addend
|
<< " addend:" << erela.r_addend
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The target section is updated with the fix up, and symbol
|
||||||
|
* section indicates the section offset being referenced by the
|
||||||
|
* fixup.
|
||||||
|
*/
|
||||||
|
|
||||||
const symbols::symbol& sym = get_symbol (GELF_R_SYM (erela.r_info));
|
const symbols::symbol& sym = get_symbol (GELF_R_SYM (erela.r_info));
|
||||||
|
|
||||||
relocation reloc (sym,
|
relocation reloc (sym,
|
||||||
|
@ -63,11 +63,6 @@ namespace rld
|
|||||||
*/
|
*/
|
||||||
relocation ();
|
relocation ();
|
||||||
|
|
||||||
/**
|
|
||||||
* The name of the symbol.
|
|
||||||
*/
|
|
||||||
std::string name () const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The offset.
|
* The offset.
|
||||||
*/
|
*/
|
||||||
@ -88,6 +83,11 @@ namespace rld
|
|||||||
*/
|
*/
|
||||||
elf_sxword addend () const;
|
elf_sxword addend () const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the symbol.
|
||||||
|
*/
|
||||||
|
const symbols::symbol& symbol () const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const symbols::symbol* sym; //< The symbol reference.
|
const symbols::symbol* sym; //< The symbol reference.
|
||||||
elf_addr offset_; //< The offset in the section.
|
elf_addr offset_; //< The offset in the section.
|
||||||
|
@ -903,11 +903,14 @@ namespace rld
|
|||||||
}
|
}
|
||||||
|
|
||||||
relocation::relocation (const elf::relocation& er)
|
relocation::relocation (const elf::relocation& er)
|
||||||
: name (er.name ()),
|
: offset (er.offset ()),
|
||||||
offset (er.offset ()),
|
|
||||||
type (er.type ()),
|
type (er.type ()),
|
||||||
info (er.info ()),
|
info (er.info ()),
|
||||||
addend (er.addend ())
|
addend (er.addend ()),
|
||||||
|
symname (er.symbol ().name ()),
|
||||||
|
symtype (er.symbol ().type ()),
|
||||||
|
symsect (er.symbol ().section_index ()),
|
||||||
|
symvalue (er.symbol ().value ())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -923,13 +926,11 @@ namespace rld
|
|||||||
offset (es.offset ()),
|
offset (es.offset ()),
|
||||||
rela (es.get_reloc_type ())
|
rela (es.get_reloc_type ())
|
||||||
{
|
{
|
||||||
load_relocations (es);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
section::load_relocations (const elf::section& es)
|
section::load_relocations (const elf::section& es)
|
||||||
{
|
{
|
||||||
rela = es.get_reloc_type ();
|
|
||||||
const elf::relocations& es_relocs = es.get_relocations ();
|
const elf::relocations& es_relocs = es.get_relocations ();
|
||||||
for (elf::relocations::const_iterator ri = es_relocs.begin ();
|
for (elf::relocations::const_iterator ri = es_relocs.begin ();
|
||||||
ri != es_relocs.end ();
|
ri != es_relocs.end ();
|
||||||
@ -937,6 +938,7 @@ namespace rld
|
|||||||
{
|
{
|
||||||
relocs.push_back (relocation (*ri));
|
relocs.push_back (relocation (*ri));
|
||||||
}
|
}
|
||||||
|
rela = es.get_reloc_type ();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
|
@ -517,11 +517,14 @@ namespace rld
|
|||||||
*/
|
*/
|
||||||
struct relocation
|
struct relocation
|
||||||
{
|
{
|
||||||
const std::string name; //< The name of the symbol.
|
|
||||||
const uint32_t offset; //< The section offset.
|
const uint32_t offset; //< The section offset.
|
||||||
const uint32_t type; //< The type of relocation record.
|
const uint32_t type; //< The type of relocation record.
|
||||||
const uint32_t info; //< The ELF info field.
|
const uint32_t info; //< The ELF info field.
|
||||||
const int32_t addend; //< The constant addend.
|
const int32_t addend; //< The constant addend.
|
||||||
|
const std::string symname; //< The name of the symbol.
|
||||||
|
const uint32_t symtype; //< The type of symbol.
|
||||||
|
const int symsect; //< The symbol's section symbol.
|
||||||
|
const uint32_t symvalue; //< The symbol's value.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct from an ELF relocation record.
|
* Construct from an ELF relocation record.
|
||||||
|
@ -66,19 +66,25 @@ namespace rld
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RAP relocation record.
|
* RAP relocation record. This one does not have const fields.
|
||||||
*/
|
*/
|
||||||
struct relocation
|
struct relocation
|
||||||
{
|
{
|
||||||
std::string name; //< The symbol name if there is one.
|
|
||||||
uint32_t offset; //< The offset in the section to apply the fixup.
|
uint32_t offset; //< The offset in the section to apply the fixup.
|
||||||
uint32_t info; //< The ELF info record.
|
uint32_t info; //< The ELF info record.
|
||||||
uint32_t addend; //< The ELF constant addend.
|
uint32_t addend; //< The ELF constant addend.
|
||||||
|
std::string symname; //< The symbol name if there is one.
|
||||||
|
uint32_t symtype; //< The type of symbol.
|
||||||
|
int symsect; //< The symbol's RAP section.
|
||||||
|
uint32_t symvalue; //< The symbol's default value.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct the relocation.
|
* Construct the relocation using the file relocation, the offset of the
|
||||||
|
* section in the target RAP section and the RAP section of the symbol.
|
||||||
*/
|
*/
|
||||||
relocation (const files::relocation& reloc, uint32_t offset = 0);
|
relocation (const files::relocation& reloc,
|
||||||
|
const uint32_t offset = 0,
|
||||||
|
const int symsect = 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -86,6 +92,13 @@ namespace rld
|
|||||||
*/
|
*/
|
||||||
typedef std::list < relocation > relocations;
|
typedef std::list < relocation > relocations;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map of object file section offsets keyed by the object file section
|
||||||
|
* index. This is used when adding the external symbols so the symbol's
|
||||||
|
* value can be adjusted by the offset of the section in the RAP section.
|
||||||
|
*/
|
||||||
|
typedef std::map < int, uint32_t > osections;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The RAP section data.
|
* The RAP section data.
|
||||||
*/
|
*/
|
||||||
@ -97,6 +110,7 @@ namespace rld
|
|||||||
uint32_t align; //< The alignment of the section.
|
uint32_t align; //< The alignment of the section.
|
||||||
bool rela; //< The relocation record has an addend field.
|
bool rela; //< The relocation record has an addend field.
|
||||||
relocations relocs; //< The relocations for this section.
|
relocations relocs; //< The relocations for this section.
|
||||||
|
osections osecs; //< The object section index.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Operator to add up section data.
|
* Operator to add up section data.
|
||||||
@ -182,12 +196,6 @@ namespace rld
|
|||||||
files::sections symtab; //< All exported symbols.
|
files::sections symtab; //< All exported symbols.
|
||||||
files::sections strtab; //< All exported strings.
|
files::sections strtab; //< All exported strings.
|
||||||
section secs[rap_secs]; //< The sections of interest.
|
section secs[rap_secs]; //< The sections of interest.
|
||||||
uint32_t symtab_off; //< The symbols section file offset.
|
|
||||||
uint32_t symtab_size; //< The symbols section size.
|
|
||||||
uint32_t strtab_off; //< The strings section file offset.
|
|
||||||
uint32_t strtab_size; //< The strings section size.
|
|
||||||
uint32_t relocs_off; //< The reloc's section file offset.
|
|
||||||
uint32_t relocs_size; //< The reloc's section size.
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The constructor. Need to have an object file to create.
|
* The constructor. Need to have an object file to create.
|
||||||
@ -204,6 +212,17 @@ namespace rld
|
|||||||
*/
|
*/
|
||||||
sections find (const uint32_t index) const;
|
sections find (const uint32_t index) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The total number of relocations in the object file.
|
||||||
|
*/
|
||||||
|
uint32_t get_relocations () const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The total number of relocations for a specific RAP section in the
|
||||||
|
* object file.
|
||||||
|
*/
|
||||||
|
uint32_t get_relocations (int sec) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* No default constructor allowed.
|
* No default constructor allowed.
|
||||||
@ -239,7 +258,7 @@ namespace rld
|
|||||||
*
|
*
|
||||||
* @param obj The object file to collection the symbol from.
|
* @param obj The object file to collection the symbol from.
|
||||||
*/
|
*/
|
||||||
void collect_symbols (const object& obj);
|
void collect_symbols (object& obj);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write the compressed output file.
|
* Write the compressed output file.
|
||||||
@ -265,16 +284,62 @@ namespace rld
|
|||||||
*/
|
*/
|
||||||
void write_relocations (compress::compressor& comp);
|
void write_relocations (compress::compressor& comp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The total number of relocations for a specific RAP section in the
|
||||||
|
* image.
|
||||||
|
*/
|
||||||
|
uint32_t get_relocations (int sec) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the image values.
|
||||||
|
*/
|
||||||
|
void clear ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the section values.
|
||||||
|
*
|
||||||
|
* @param index The RAP section index to update.
|
||||||
|
* @param sec The object's RAP section.
|
||||||
|
*/
|
||||||
|
void update_section (int index, const section& sec);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
objects objs; //< The RAP objects
|
objects objs; //< The RAP objects
|
||||||
section secs[rap_secs]; //< The sections of interest.
|
uint32_t sec_size[rap_secs]; //< The sections of interest.
|
||||||
|
uint32_t sec_align[rap_secs]; //< The sections of interest.
|
||||||
|
bool sec_rela[rap_secs]; //< The sections of interest.
|
||||||
externals externs; //< The symbols in the image
|
externals externs; //< The symbols in the image
|
||||||
uint32_t symtab_size; //< The size of the symbols.
|
uint32_t symtab_size; //< The size of the symbols.
|
||||||
std::string strtab; //< The strings table.
|
std::string strtab; //< The strings table.
|
||||||
uint32_t relocs_size; //< The relocations size.
|
uint32_t relocs_size; //< The relocations size.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the offset taking into account the alignment.
|
||||||
|
*
|
||||||
|
* @param offset The current offset.
|
||||||
|
* @param size The size to move the offset by.
|
||||||
|
* @param alignment The alignment of the offset.
|
||||||
|
* @return uint32_t The new aligned offset.
|
||||||
|
*/
|
||||||
|
uint32_t align_offset (uint32_t offset, uint32_t size, uint32_t alignment)
|
||||||
|
{
|
||||||
|
offset += size;
|
||||||
|
|
||||||
|
if (alignment > 1)
|
||||||
|
{
|
||||||
|
uint32_t mask = alignment - 1;
|
||||||
|
if (offset & mask)
|
||||||
|
{
|
||||||
|
offset &= ~mask;
|
||||||
|
offset += alignment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Output helper function to report the sections in an object file.
|
* Output helper function to report the sections in an object file.
|
||||||
* This is useful when seeing the flags in the sections.
|
* This is useful when seeing the flags in the sections.
|
||||||
@ -329,18 +394,24 @@ namespace rld
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
relocation::relocation (const files::relocation& reloc, uint32_t offset)
|
relocation::relocation (const files::relocation& reloc,
|
||||||
: name (reloc.name),
|
const uint32_t offset,
|
||||||
offset (offset + reloc.offset),
|
const int symsect)
|
||||||
|
: offset (reloc.offset + offset),
|
||||||
info (reloc.info),
|
info (reloc.info),
|
||||||
addend (reloc.info)
|
addend (reloc.addend),
|
||||||
|
symname (reloc.symname),
|
||||||
|
symtype (reloc.symtype),
|
||||||
|
symsect (symsect),
|
||||||
|
symvalue (reloc.symvalue)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
section::section ()
|
section::section ()
|
||||||
: size (0),
|
: size (0),
|
||||||
offset (0),
|
offset (0),
|
||||||
align (0)
|
align (0),
|
||||||
|
rela (false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,6 +421,7 @@ namespace rld
|
|||||||
size = 0;
|
size = 0;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
align = 0;
|
align = 0;
|
||||||
|
rela = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
section&
|
section&
|
||||||
@ -370,6 +442,8 @@ namespace rld
|
|||||||
size += sec.size;
|
size += sec.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rela = sec.rela;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,25 +460,7 @@ namespace rld
|
|||||||
void
|
void
|
||||||
section::set_offset (const section& sec)
|
section::set_offset (const section& sec)
|
||||||
{
|
{
|
||||||
offset = sec.offset + sec.size;
|
offset = align_offset (sec.offset, sec.size, align);
|
||||||
|
|
||||||
if (align > 1)
|
|
||||||
{
|
|
||||||
uint32_t mask = align - 1;
|
|
||||||
if (offset & mask)
|
|
||||||
{
|
|
||||||
offset &= ~mask;
|
|
||||||
offset += align;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (relocations::iterator ri = relocs.begin ();
|
|
||||||
ri != relocs.end ();
|
|
||||||
++ri)
|
|
||||||
{
|
|
||||||
relocation& reloc = *ri;
|
|
||||||
reloc.offset += offset;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -418,36 +474,86 @@ namespace rld
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper for for_each to get the relocations.
|
* Helper for for_each to merge the related object sections into the RAP
|
||||||
|
* section.
|
||||||
*/
|
*/
|
||||||
class section_relocs:
|
class section_merge:
|
||||||
public std::unary_function < const files::section, void >
|
public std::unary_function < const files::section, void >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
section_relocs (section& sec);
|
section_merge (object& obj, section& sec);
|
||||||
|
|
||||||
void operator () (const files::section& fsec);
|
void operator () (const files::section& fsec);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
object& obj;
|
||||||
section& sec;
|
section& sec;
|
||||||
};
|
};
|
||||||
|
|
||||||
section_relocs::section_relocs (section& sec)
|
section_merge::section_merge (object& obj, section& sec)
|
||||||
: sec (sec)
|
: obj (obj),
|
||||||
|
sec (sec)
|
||||||
{
|
{
|
||||||
|
sec.align = 0;
|
||||||
|
sec.offset = 0;
|
||||||
|
sec.size = 0;
|
||||||
|
sec.rela = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
section_relocs::operator () (const files::section& fsec)
|
section_merge::operator () (const files::section& fsec)
|
||||||
{
|
{
|
||||||
for (files::relocations::const_iterator ri = fsec.relocs.begin ();
|
if (sec.align == 0)
|
||||||
ri != fsec.relocs.end ();
|
sec.align = fsec.alignment;
|
||||||
++ri)
|
else if (sec.align != fsec.alignment)
|
||||||
|
throw rld::error ("Alignments do not match for section '" + sec.name + "'",
|
||||||
|
"rap::section");
|
||||||
|
|
||||||
|
uint32_t offset = align_offset (sec.size, 0, sec.align);
|
||||||
|
|
||||||
|
if (1 || rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
|
||||||
|
std::cout << "rap:section-merge: relocs=" << fsec.relocs.size ()
|
||||||
|
<< " offset=" << offset
|
||||||
|
<< " fsec.name=" << fsec.name
|
||||||
|
<< " fsec.size=" << fsec.size
|
||||||
|
<< " fsec.alignment=" << fsec.alignment
|
||||||
|
<< " " << obj.obj.name ().full () << std::endl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add the object file's section offset to the map. This is needed
|
||||||
|
* to adjust the external symbol offsets.
|
||||||
|
*/
|
||||||
|
sec.osecs[fsec.index] = offset;
|
||||||
|
|
||||||
|
uint32_t rc = 0;
|
||||||
|
|
||||||
|
for (files::relocations::const_iterator fri = fsec.relocs.begin ();
|
||||||
|
fri != fsec.relocs.end ();
|
||||||
|
++fri, ++rc)
|
||||||
{
|
{
|
||||||
sec.relocs.push_back (relocation (*ri, sec.offset));
|
const files::relocation& freloc = *fri;
|
||||||
|
|
||||||
|
if (1 || rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
|
||||||
|
std::cout << " " << std::setw (2) << sec.relocs.size ()
|
||||||
|
<< '/' << std::setw (2) << rc
|
||||||
|
<< std::hex << ": reloc.info=0x" << freloc.info << std::dec
|
||||||
|
<< " reloc.offset=" << freloc.offset
|
||||||
|
<< " reloc.addend=" << freloc.addend
|
||||||
|
<< " reloc.symtype=" << freloc.symtype
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
if (freloc.symtype == STT_NOTYPE)
|
||||||
|
sec.relocs.push_back (relocation (freloc, offset));
|
||||||
|
else
|
||||||
|
sec.relocs.push_back (relocation (freloc,
|
||||||
|
offset,
|
||||||
|
obj.find (freloc.symsect)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sec.rela = fsec.rela;
|
||||||
|
sec.size = offset + fsec.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
external::external (const uint32_t name,
|
external::external (const uint32_t name,
|
||||||
@ -470,13 +576,7 @@ namespace rld
|
|||||||
}
|
}
|
||||||
|
|
||||||
object::object (files::object& obj)
|
object::object (files::object& obj)
|
||||||
: obj (obj),
|
: obj (obj)
|
||||||
symtab_off (0),
|
|
||||||
symtab_size (0),
|
|
||||||
strtab_off (0),
|
|
||||||
strtab_size (0),
|
|
||||||
relocs_off (0),
|
|
||||||
relocs_size (0)
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Set up the names of the sections.
|
* Set up the names of the sections.
|
||||||
@ -485,8 +585,9 @@ namespace rld
|
|||||||
secs[s].name = section_names[s];
|
secs[s].name = section_names[s];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the relocation records. Setting the offset will update them.
|
* Get the relocation records. Collect the various section types from the
|
||||||
* section.
|
* object file into the RAP sections. Merge those sections into the RAP
|
||||||
|
* sections.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
obj.open ();
|
obj.open ();
|
||||||
@ -495,18 +596,14 @@ namespace rld
|
|||||||
obj.begin ();
|
obj.begin ();
|
||||||
obj.load_relocations ();
|
obj.load_relocations ();
|
||||||
obj.end ();
|
obj.end ();
|
||||||
obj.close ();
|
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
obj.close ();
|
obj.close ();
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
obj.close ();
|
||||||
|
|
||||||
/*
|
|
||||||
* Get from the object file the various sections we need to format a
|
|
||||||
* memory layout.
|
|
||||||
*/
|
|
||||||
obj.get_sections (text, SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
|
obj.get_sections (text, SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
|
||||||
obj.get_sections (const_, SHT_PROGBITS, SHF_ALLOC | SHF_MERGE, SHF_WRITE | SHF_EXECINSTR);
|
obj.get_sections (const_, SHT_PROGBITS, SHF_ALLOC | SHF_MERGE, SHF_WRITE | SHF_EXECINSTR);
|
||||||
obj.get_sections (ctor, ".ctors");
|
obj.get_sections (ctor, ".ctors");
|
||||||
@ -516,33 +613,20 @@ namespace rld
|
|||||||
obj.get_sections (symtab, SHT_SYMTAB);
|
obj.get_sections (symtab, SHT_SYMTAB);
|
||||||
obj.get_sections (strtab, ".strtab");
|
obj.get_sections (strtab, ".strtab");
|
||||||
|
|
||||||
secs[rap_text].update (text);
|
|
||||||
secs[rap_const].update (const_);
|
|
||||||
secs[rap_ctor].update (ctor);
|
|
||||||
secs[rap_dtor].update (dtor);
|
|
||||||
secs[rap_data].update (data);
|
|
||||||
secs[rap_bss].update (bss);
|
|
||||||
|
|
||||||
std::for_each (text.begin (), text.end (),
|
std::for_each (text.begin (), text.end (),
|
||||||
section_relocs (secs[rap_text]));
|
section_merge (*this, secs[rap_text]));
|
||||||
std::for_each (const_.begin (), const_.end (),
|
std::for_each (const_.begin (), const_.end (),
|
||||||
section_relocs (secs[rap_const]));
|
section_merge (*this, secs[rap_const]));
|
||||||
std::for_each (ctor.begin (), ctor.end (),
|
std::for_each (ctor.begin (), ctor.end (),
|
||||||
section_relocs (secs[rap_ctor]));
|
section_merge (*this, secs[rap_ctor]));
|
||||||
std::for_each (dtor.begin (), dtor.end (),
|
std::for_each (dtor.begin (), dtor.end (),
|
||||||
section_relocs (secs[rap_dtor]));
|
section_merge (*this, secs[rap_dtor]));
|
||||||
std::for_each (data.begin (), data.end (),
|
std::for_each (data.begin (), data.end (),
|
||||||
section_relocs (secs[rap_data]));
|
section_merge (*this, secs[rap_data]));
|
||||||
std::for_each (bss.begin (), bss.end (),
|
std::for_each (bss.begin (), bss.end (),
|
||||||
section_relocs (secs[rap_bss]));
|
section_merge (*this, secs[rap_bss]));
|
||||||
|
|
||||||
symtab_size = files::sum_sizes (symtab);
|
if (1 || rld::verbose () >= RLD_VERBOSE_TRACE)
|
||||||
strtab_size = files::sum_sizes (strtab);
|
|
||||||
relocs_size = 0;
|
|
||||||
for (int s = 0; s < rap_secs; ++s)
|
|
||||||
relocs_size += secs[s].relocs.size ();
|
|
||||||
|
|
||||||
if (rld::verbose () >= RLD_VERBOSE_TRACE)
|
|
||||||
{
|
{
|
||||||
std::cout << "rap:object: " << obj.name ().full () << std::endl;
|
std::cout << "rap:object: " << obj.name ().full () << std::endl;
|
||||||
output ("text", secs[rap_text].size, text);
|
output ("text", secs[rap_text].size, text);
|
||||||
@ -552,10 +636,6 @@ namespace rld
|
|||||||
output ("data", secs[rap_data].size, data);
|
output ("data", secs[rap_data].size, data);
|
||||||
if (secs[rap_bss].size)
|
if (secs[rap_bss].size)
|
||||||
std::cout << " bss: size: " << secs[rap_bss].size << std::endl;
|
std::cout << " bss: size: " << secs[rap_bss].size << std::endl;
|
||||||
output ("symtab", symtab_size, symtab);
|
|
||||||
output ("strtab", strtab_size, strtab);
|
|
||||||
if (relocs_size)
|
|
||||||
std::cout << " relocs: size: " << relocs_size << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -568,13 +648,7 @@ namespace rld
|
|||||||
data (orig.data),
|
data (orig.data),
|
||||||
bss (orig.bss),
|
bss (orig.bss),
|
||||||
symtab (orig.symtab),
|
symtab (orig.symtab),
|
||||||
strtab (orig.strtab),
|
strtab (orig.strtab)
|
||||||
symtab_off (orig.symtab_off),
|
|
||||||
symtab_size (orig.symtab_size),
|
|
||||||
strtab_off (orig.strtab_off),
|
|
||||||
strtab_size (orig.strtab_size),
|
|
||||||
relocs_off (orig.relocs_off),
|
|
||||||
relocs_size (orig.relocs_size)
|
|
||||||
{
|
{
|
||||||
for (int s = 0; s < rap_secs; ++s)
|
for (int s = 0; s < rap_secs; ++s)
|
||||||
secs[s] = orig.secs[s];
|
secs[s] = orig.secs[s];
|
||||||
@ -613,20 +687,34 @@ namespace rld
|
|||||||
"' not found: " + obj.name ().full (), "rap::object");
|
"' not found: " + obj.name ().full (), "rap::object");
|
||||||
}
|
}
|
||||||
|
|
||||||
image::image ()
|
uint32_t
|
||||||
: symtab_size (0),
|
object::get_relocations () const
|
||||||
relocs_size (0)
|
|
||||||
{
|
{
|
||||||
/*
|
uint32_t relocs = 0;
|
||||||
* Set up the names of the sections.
|
|
||||||
*/
|
|
||||||
for (int s = 0; s < rap_secs; ++s)
|
for (int s = 0; s < rap_secs; ++s)
|
||||||
secs[s].name = section_names[s];
|
relocs += secs[s].relocs.size ();
|
||||||
|
return relocs;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
object::get_relocations (int sec) const
|
||||||
|
{
|
||||||
|
if ((sec < 0) || (sec >= rap_secs))
|
||||||
|
throw rld::error ("Invalid section index '" + rld::to_string (index),
|
||||||
|
"rap::relocations");
|
||||||
|
return secs[sec].relocs.size ();
|
||||||
|
}
|
||||||
|
|
||||||
|
image::image ()
|
||||||
|
{
|
||||||
|
clear ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
image::layout (const files::object_list& app_objects)
|
image::layout (const files::object_list& app_objects)
|
||||||
{
|
{
|
||||||
|
clear ();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create the local objects which contain the layout information.
|
* Create the local objects which contain the layout information.
|
||||||
*/
|
*/
|
||||||
@ -643,12 +731,6 @@ namespace rld
|
|||||||
objs.push_back (object (app_obj));
|
objs.push_back (object (app_obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int s = 0; s < rap_secs; ++s)
|
|
||||||
secs[s].clear ();
|
|
||||||
|
|
||||||
symtab_size = 0;
|
|
||||||
strtab.clear ();
|
|
||||||
|
|
||||||
for (objects::iterator oi = objs.begin (), poi = objs.begin ();
|
for (objects::iterator oi = objs.begin (), poi = objs.begin ();
|
||||||
oi != objs.end ();
|
oi != objs.end ();
|
||||||
++oi)
|
++oi)
|
||||||
@ -663,35 +745,32 @@ namespace rld
|
|||||||
if (oi != objs.begin ())
|
if (oi != objs.begin ())
|
||||||
{
|
{
|
||||||
object& pobj = *poi;
|
object& pobj = *poi;
|
||||||
for (int s = 1; s < rap_secs; ++s)
|
for (int s = 0; s < rap_secs; ++s)
|
||||||
obj.secs[s].set_offset (pobj.secs[s]);
|
obj.secs[s].set_offset (pobj.secs[s]);
|
||||||
++poi;
|
++poi;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int s = 0; s < rap_secs; ++s)
|
for (int s = 0; s < rap_secs; ++s)
|
||||||
secs[s] += obj.secs[s];
|
update_section (s, obj.secs[s]);
|
||||||
|
|
||||||
collect_symbols (obj);
|
collect_symbols (obj);
|
||||||
|
|
||||||
relocs_size += obj.relocs_size;
|
relocs_size += obj.get_relocations ();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int s = 1; s < rap_secs; ++s)
|
|
||||||
secs[s].set_offset (secs[s - 1]);
|
|
||||||
|
|
||||||
if (1 || rld::verbose () >= RLD_VERBOSE_INFO)
|
if (1 || rld::verbose () >= RLD_VERBOSE_INFO)
|
||||||
{
|
{
|
||||||
uint32_t total = (secs[rap_text].size + secs[rap_data].size +
|
uint32_t total = (sec_size[rap_text] + sec_size[rap_data] +
|
||||||
secs[rap_data].size + secs[rap_bss].size +
|
sec_size[rap_data] + sec_size[rap_bss] +
|
||||||
symtab_size + strtab.size() + relocs_size);
|
symtab_size + strtab.size() + relocs_size);
|
||||||
std::cout << "rap::layout: total:" << total
|
std::cout << "rap::layout: total:" << total
|
||||||
<< " text:" << secs[rap_text].size << " (" << secs[rap_text].offset
|
<< " text:" << sec_size[rap_text]
|
||||||
<< ") const:" << secs[rap_const].size << " (" << secs[rap_const].offset
|
<< " const:" << sec_size[rap_const]
|
||||||
<< ") ctor:" << secs[rap_ctor].size << " (" << secs[rap_ctor].offset
|
<< " ctor:" << sec_size[rap_ctor]
|
||||||
<< ") dtor:" << secs[rap_dtor].size << " (" << secs[rap_dtor].offset
|
<< " dtor:" << sec_size[rap_dtor]
|
||||||
<< ") data:" << secs[rap_data].size << " (" << secs[rap_data].offset
|
<< " data:" << sec_size[rap_data]
|
||||||
<< ") bss:" << secs[rap_bss].size << " (" << secs[rap_bss].offset
|
<< " bss:" << sec_size[rap_bss]
|
||||||
<< ") symbols:" << symtab_size << " (" << externs.size () << ')'
|
<< " symbols:" << symtab_size << " (" << externs.size () << ')'
|
||||||
<< " strings:" << strtab.size ()
|
<< " strings:" << strtab.size ()
|
||||||
<< " relocs:" << relocs_size
|
<< " relocs:" << relocs_size
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
@ -699,7 +778,7 @@ namespace rld
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
image::collect_symbols (const object& obj)
|
image::collect_symbols (object& obj)
|
||||||
{
|
{
|
||||||
symbols::pointers& esyms = obj.obj.external_symbols ();
|
symbols::pointers& esyms = obj.obj.external_symbols ();
|
||||||
for (symbols::pointers::const_iterator ei = esyms.begin ();
|
for (symbols::pointers::const_iterator ei = esyms.begin ();
|
||||||
@ -712,10 +791,21 @@ namespace rld
|
|||||||
{
|
{
|
||||||
if ((sym.binding () == STB_GLOBAL) || (sym.binding () == STB_WEAK))
|
if ((sym.binding () == STB_GLOBAL) || (sym.binding () == STB_WEAK))
|
||||||
{
|
{
|
||||||
|
int symsec = sym.section_index ();
|
||||||
|
sections rap_sec = obj.find (symsec);
|
||||||
|
section& sec = obj.secs[rap_sec];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The '+ 2' is for the end of string nul and the delimiting nul.
|
||||||
|
*
|
||||||
|
* The symbol's value is the symbols value plus the offset of the
|
||||||
|
* object file's section offset in the RAP section.
|
||||||
|
*/
|
||||||
externs.push_back (external (strtab.size () + 2,
|
externs.push_back (external (strtab.size () + 2,
|
||||||
obj.find (sym.section_index ()),
|
rap_sec,
|
||||||
sym.value (),
|
sec.osecs[symsec] + sym.value (),
|
||||||
sym.info ()));
|
sym.info ()));
|
||||||
|
|
||||||
symtab_size += external::rap_size;
|
symtab_size += external::rap_size;
|
||||||
strtab += sym.name ();
|
strtab += sym.name ();
|
||||||
strtab += '\0';
|
strtab += '\0';
|
||||||
@ -757,6 +847,9 @@ namespace rld
|
|||||||
void
|
void
|
||||||
section_writer::operator () (object& obj)
|
section_writer::operator () (object& obj)
|
||||||
{
|
{
|
||||||
|
if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
|
||||||
|
std::cout << "rap:writing: " << section_names[sec] << std::endl;
|
||||||
|
|
||||||
switch (sec)
|
switch (sec)
|
||||||
{
|
{
|
||||||
case rap_text:
|
case rap_text:
|
||||||
@ -809,9 +902,8 @@ namespace rld
|
|||||||
<< (uint32_t) 0;
|
<< (uint32_t) 0;
|
||||||
|
|
||||||
for (int s = 0; s < rap_secs; ++s)
|
for (int s = 0; s < rap_secs; ++s)
|
||||||
comp << secs[s].size
|
comp << sec_size[s]
|
||||||
<< secs[s].align
|
<< sec_align[s];
|
||||||
<< secs[s].offset;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Output the sections from each object file.
|
* Output the sections from each object file.
|
||||||
@ -839,19 +931,46 @@ namespace rld
|
|||||||
files::object& obj,
|
files::object& obj,
|
||||||
const files::sections& secs)
|
const files::sections& secs)
|
||||||
{
|
{
|
||||||
|
uint32_t offset = 0;
|
||||||
|
uint32_t size = 0;
|
||||||
|
|
||||||
obj.open ();
|
obj.open ();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
obj.begin ();
|
obj.begin ();
|
||||||
|
|
||||||
|
if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
|
||||||
|
std::cout << "rap:write sections: " << obj.name ().full () << std::endl;
|
||||||
|
|
||||||
for (files::sections::const_iterator si = secs.begin ();
|
for (files::sections::const_iterator si = secs.begin ();
|
||||||
si != secs.end ();
|
si != secs.end ();
|
||||||
++si)
|
++si)
|
||||||
{
|
{
|
||||||
const files::section& sec = *si;
|
const files::section& sec = *si;
|
||||||
comp.write (obj, sec.offset, sec.size);
|
uint32_t unaligned_offset = offset + size;
|
||||||
|
|
||||||
|
offset = align_offset (offset, size, sec.alignment);
|
||||||
|
|
||||||
|
if (offset != unaligned_offset)
|
||||||
|
{
|
||||||
|
char ee = '\xee';
|
||||||
|
for (uint32_t p = 0; p < (offset - unaligned_offset); ++p)
|
||||||
|
comp.write (&ee, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
comp.write (obj, sec.offset, sec.size);
|
||||||
|
|
||||||
|
if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
|
||||||
|
std::cout << " offset=" << offset
|
||||||
|
<< " padding=" << (offset - unaligned_offset) << std::endl;
|
||||||
|
|
||||||
|
size = sec.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
|
||||||
|
std::cout << " -- size=" << offset << std::endl;
|
||||||
|
|
||||||
obj.end ();
|
obj.end ();
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
@ -880,46 +999,172 @@ namespace rld
|
|||||||
void
|
void
|
||||||
image::write_relocations (compress::compressor& comp)
|
image::write_relocations (compress::compressor& comp)
|
||||||
{
|
{
|
||||||
|
for (int s = 0; s < rap_secs; ++s)
|
||||||
|
{
|
||||||
|
uint32_t count = get_relocations (s);
|
||||||
|
uint32_t sr = 0;
|
||||||
|
uint32_t header;
|
||||||
|
|
||||||
|
if (1 || rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
|
||||||
|
std::cout << "rep:relocation: section:" << section_names[s]
|
||||||
|
<< " relocs=" << count
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
header = count;
|
||||||
|
header |= sec_rela[s] ? (1UL << 31) : 0;
|
||||||
|
|
||||||
|
comp << header;
|
||||||
|
|
||||||
for (objects::iterator oi = objs.begin ();
|
for (objects::iterator oi = objs.begin ();
|
||||||
oi != objs.end ();
|
oi != objs.end ();
|
||||||
++oi)
|
++oi)
|
||||||
{
|
{
|
||||||
object& obj = *oi;
|
object& obj = *oi;
|
||||||
for (int s = 0; s < rap_secs; ++s)
|
|
||||||
{
|
|
||||||
section& sec = obj.secs[s];
|
section& sec = obj.secs[s];
|
||||||
relocations& relocs = sec.relocs;
|
relocations& relocs = sec.relocs;
|
||||||
uint32_t header = relocs.size ();
|
uint32_t rc = 0;
|
||||||
|
|
||||||
header |= sec.rela ? (1 << 31) : 0;
|
if (1 || rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
|
||||||
|
std::cout << " relocs=" << sec.relocs.size ()
|
||||||
comp << header;
|
<< " sec.offset=" << sec.offset
|
||||||
|
<< " sec.size=" << sec.size
|
||||||
|
<< " sec.align=" << sec.align
|
||||||
|
<< " " << obj.obj.name ().full () << std::endl;
|
||||||
|
|
||||||
for (relocations::const_iterator ri = relocs.begin ();
|
for (relocations::const_iterator ri = relocs.begin ();
|
||||||
ri != relocs.end ();
|
ri != relocs.end ();
|
||||||
++ri)
|
++ri, ++sr, ++rc)
|
||||||
{
|
{
|
||||||
const relocation& reloc = *ri;
|
const relocation& reloc = *ri;
|
||||||
std::size_t size = strtab.find (reloc.name);
|
|
||||||
uint32_t info = GELF_R_TYPE (reloc.info);
|
uint32_t info = GELF_R_TYPE (reloc.info);
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t addend = reloc.addend;
|
||||||
|
bool write_addend = sec.rela;
|
||||||
|
bool write_symname = false;
|
||||||
|
|
||||||
if (size)
|
offset = sec.offset + reloc.offset;
|
||||||
info |= size << 8;
|
|
||||||
|
if (reloc.symtype == STT_SECTION)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Bit 31 clear, bits 30:8 RAP section index.
|
||||||
|
*/
|
||||||
|
info |= reloc.symsect << 8;
|
||||||
|
|
||||||
|
addend += obj.secs[reloc.symsect].offset + reloc.symvalue;
|
||||||
|
|
||||||
|
write_addend = true;
|
||||||
|
|
||||||
|
if (1 || rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
|
||||||
|
std::cout << " " << std::setw (2) << sr << '/' << std::setw (2) << rc
|
||||||
|
<<": rsym: sect=" << section_names[reloc.symsect]
|
||||||
|
<< " sec.offset=" << obj.secs[reloc.symsect].offset
|
||||||
|
<< " reloc.symsect=" << reloc.symsect
|
||||||
|
<< " reloc.symvalue=" << reloc.symvalue
|
||||||
|
<< " reloc.addend=" << reloc.addend
|
||||||
|
<< " addend=" << addend
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
info |= (1 << 31) | (reloc.name.size () << 8);
|
{
|
||||||
|
/*
|
||||||
|
* Bit 31 must be set. Bit 30 determines the type of string and
|
||||||
|
* bits 29:8 the strtab offset or the size of the appended
|
||||||
|
* string.
|
||||||
|
*/
|
||||||
|
|
||||||
comp << info << reloc.offset;
|
info |= 1 << 31;
|
||||||
|
|
||||||
if (sec.rela)
|
std::size_t size = strtab.find (reloc.symname);
|
||||||
comp << reloc.addend;
|
|
||||||
|
|
||||||
if (!size)
|
if (size == std::string::npos)
|
||||||
comp << reloc.name;
|
{
|
||||||
|
/*
|
||||||
|
* Bit 30 clear, the size of the symbol name.
|
||||||
|
*/
|
||||||
|
info |= reloc.symname.size () << 8;
|
||||||
|
write_symname = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Bit 30 set, the offset in the strtab.
|
||||||
|
*/
|
||||||
|
info |= (1 << 30) | (size << 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1 || rld::verbose () >= RLD_VERBOSE_FULL_DEBUG)
|
||||||
|
{
|
||||||
|
std::cout << " " << std::setw (2) << sr << '/'
|
||||||
|
<< std::setw (2) << rc
|
||||||
|
<< std::hex << ": reloc: info=0x" << info << std::dec
|
||||||
|
<< " offset=" << offset;
|
||||||
|
if (write_addend)
|
||||||
|
std::cout << " addend=" << addend;
|
||||||
|
if (write_symname)
|
||||||
|
std::cout << " symname=" << reloc.symname;
|
||||||
|
std::cout << std::hex
|
||||||
|
<< " reloc.info=0x" << reloc.info << std::dec
|
||||||
|
<< " reloc.offset=" << reloc.offset
|
||||||
|
<< " reloc.symtype=" << reloc.symtype
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
comp << info << offset;
|
||||||
|
|
||||||
|
if (write_addend)
|
||||||
|
comp << addend;
|
||||||
|
|
||||||
|
if (write_symname)
|
||||||
|
comp << reloc.symname;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
image::get_relocations (int sec) const
|
||||||
|
{
|
||||||
|
if ((sec < 0) || (sec >= rap_secs))
|
||||||
|
throw rld::error ("Invalid section index '" + rld::to_string (index),
|
||||||
|
"rap::image::relocations");
|
||||||
|
|
||||||
|
uint32_t relocs = 0;
|
||||||
|
|
||||||
|
for (objects::const_iterator oi = objs.begin ();
|
||||||
|
oi != objs.end ();
|
||||||
|
++oi)
|
||||||
|
{
|
||||||
|
const object& obj = *oi;
|
||||||
|
relocs += obj.get_relocations (sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
return relocs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
image::clear ()
|
||||||
|
{
|
||||||
|
for (int s = 0; s < rap_secs; ++s)
|
||||||
|
{
|
||||||
|
sec_size[s] = 0;
|
||||||
|
sec_align[s] = 0;
|
||||||
|
sec_rela[s] = false;
|
||||||
|
}
|
||||||
|
symtab_size = 0;
|
||||||
|
strtab.clear ();
|
||||||
|
relocs_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
image::update_section (int index, const section& sec)
|
||||||
|
{
|
||||||
|
sec_size[index] += sec.size;
|
||||||
|
sec_align[index] = sec.align;
|
||||||
|
sec_rela[index] = sec.rela;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
write (files::image& app,
|
write (files::image& app,
|
||||||
const std::string& init,
|
const std::string& init,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user