owelf.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 481 行 · 第 1/2 页
C
481 行
switch( section->align ) {
case 1:
case 2:
case 4:
case 8:
case 16:
case 32:
case 64:
alignment = section->align;
break;
default:
assert( 0 ); // must be power of two
break;
}
return( alignment );
}
static owl_offset sectionPadding( owl_section_handle section, owl_offset offset )
//*******************************************************************************
{
owl_offset mod;
owl_offset padding;
padding = 0;
if( section->align != 0 ) {
mod = offset % section->align;
if( mod != 0 ) {
padding = section->align - mod;
}
}
section->x.elf.pad_amount = padding;
return( padding );
}
static void doSectionHeader( owl_section_handle section, Elf32_Shdr *header )
//***************************************************************************
{
initSectionHeader( header, sectionTypes( section->type ), sectionFlags( section->type ) );
header->sh_name = OWLStringOffset( section->name );
header->sh_addralign = sectionAlignment( section );
header->sh_size = section->size + sectionPadding( section, section->size );
if( !( section->type & OWL_SEC_ATTR_BSS ) ) {
header->sh_offset = section->file->x.elf.next_section;
section->file->x.elf.next_section += header->sh_size;
}
}
static void doSectionRelocsHeader( owl_section_handle section, Elf32_Shdr *header ) {
//***********************************************************************************
size_t reloc_entry_size;
reloc_entry_size = useRela ? sizeof( Elf32_Rela ) : sizeof( Elf32_Rel );
initSectionHeader( header, (useRela ? SHT_RELA : SHT_REL), sectionFlags( section->type ) & SHF_ALLOC );
header->sh_name = OWLStringOffset( section->x.elf.relocs_name );
header->sh_link = ELF_SYMBOL_INDEX;
header->sh_info = _OWLIndexToELFIndex( section->index );
header->sh_size = reloc_entry_size * section->num_relocs;
header->sh_entsize = reloc_entry_size;
header->sh_offset = section->file->x.elf.next_section;
section->file->x.elf.next_section += header->sh_size;
}
static void formatUserSectionHeaders( owl_file_handle file, Elf32_Shdr *headers ) {
//*********************************************************************************
owl_section_handle curr;
for( curr = file->sections; curr != NULL; curr = curr->next ) {
doSectionHeader( curr, &headers[ _OWLIndexToELFIndex( curr->index ) ] );
if( curr->first_reloc != NULL ) {
doSectionRelocsHeader( curr, &headers[ _OWLIndexToELFIndex( curr->x.elf.relocs_index ) ] );
}
}
}
static void emitSectionHeaders( owl_file_handle file ) {
//******************************************************
Elf32_Shdr *headers;
Elf32_Word section_header_table_size;
section_header_table_size = numSections( file ) * sizeof( Elf32_Shdr );
file->x.elf.next_section = sizeof( Elf32_Ehdr ) + section_header_table_size;
headers = _ClientAlloc( file, section_header_table_size );
formatBogusUndefHeader( file, &headers[ ELF_UNDEF_INDEX ] );
formatStringTableHeader( file, &headers[ ELF_STRING_INDEX ] );
formatSymbolTableHeader( file, &headers[ ELF_SYMBOL_INDEX ] );
formatUserSectionHeaders( file, headers );
_ClientWrite( file, (const char *)headers, section_header_table_size );
_ClientFree( file, headers );
}
static void emitSpecialSection( owl_file_handle file, elf_special_section *section ) {
//************************************************************************************
_ClientWrite( file, section->buffer, section->length );
_ClientFree( file, section->buffer );
}
static void emitReloc( owl_section_handle sec, owl_reloc_info *reloc, Elf32_Rela *elf_reloc ) {
//*********************************************************************************************
owl_offset old_loc;
unsigned_32 data;
unsigned_32 bit_mask;
size_t data_size;
elf_reloc->r_offset = reloc->location;
elf_reloc->r_info = ELF32_R_INFO( reloc->symbol->index, ElfRelocType( reloc->type, sec->file->info->cpu ) );
bit_mask = OWLRelocBitMask( sec->file, reloc );
#ifdef __BIG_ENDIAN__ //TODO check target, not host
// When targeting big endian machines, halfword relocs do not start
// where the instruction starts because high bits are stored first and
// reloc is in the low bits. Adjust the location of the reloc for those.
// Bit of a hack really, but this is the easiest place to do it.
if( !(bit_mask & 0xffff0000) )
elf_reloc->r_offset += 2;
#endif
if( useRela ) {
// dig up the embedded addend within the object and put it here
old_loc = OWLBufferTell( sec->buffer );
OWLBufferSeek( sec->buffer, reloc->location );
data = 0;
data_size = min( 4, OWLBufferSize( sec->buffer ) - reloc->location );
OWLBufferRead( sec->buffer, reloc->location, (char *)&data, data_size );
elf_reloc->r_addend = ( data & bit_mask );
data &= ~bit_mask;
OWLBufferWrite( sec->buffer, (char *)&data, data_size );
OWLBufferSeek( sec->buffer, old_loc );
}
}
static void emitSectionPadding( owl_section_info *curr )
//******************************************************
{
char *buffer;
owl_offset padding;
padding = curr->x.elf.pad_amount;
if( padding != 0 ) {
buffer = _ClientAlloc( curr->file, padding );
memset( buffer, 0, padding );
_ClientWrite( curr->file, buffer, padding );
_ClientFree( curr->file, buffer );
}
}
static void emitSectionData( owl_file_handle file ) {
//***************************************************
owl_section_handle curr;
owl_reloc_info *reloc;
owl_offset relocs_size;
Elf32_Rela *reloc_buffer;
Elf32_Rela *next_reloc;
size_t reloc_entry_size;
// Depending on useRela, the last field of Elf32_Rela might be unused.
// We pass rela ptr around because it works for rel case also.
// So be careful: don't do a ++next_reloc etc and expect it to be correct.
reloc_entry_size = useRela ? sizeof( Elf32_Rela ) : sizeof( Elf32_Rel );
for( curr = file->sections; curr != NULL; curr = curr->next ) {
// We need to prepare the reloc data before emitting its corresponding
// section because we might need to modify the buffer content.
// (see emitReloc)
if( curr->first_reloc != NULL ) {
relocs_size = reloc_entry_size * curr->num_relocs;
reloc_buffer = _ClientAlloc( file, relocs_size );
next_reloc = reloc_buffer;
for( reloc = curr->first_reloc; reloc != NULL; reloc = reloc->next ) {
emitReloc( curr, reloc, next_reloc );
next_reloc = (Elf32_Rela *)((unsigned)next_reloc + reloc_entry_size);
}
} else {
reloc_buffer = NULL;
}
if( !_OwlSectionBSS( curr ) ) {
OWLBufferEmit( curr->buffer );
emitSectionPadding( curr );
}
if( reloc_buffer ) {
// Now write out the prepared reloc_buffer
_ClientWrite( file, (const char *)reloc_buffer, relocs_size );
_ClientFree( file, reloc_buffer );
}
}
}
static void prepareRelocSections( owl_file_handle file ) {
//********************************************************
// Run through the user-defined sections noting which ones have
// relocs and allocate a section index for the section which will
// hold those relocs - also, alloc names for them in the string table
owl_section_handle curr;
char buffer[ MAX_SECTION_NAME + 5 ];
switch( file->info->cpu ) {
case OWL_CPU_INTEL:
case OWL_CPU_MIPS: // MIPS SysV ABI supplement says so
useRela = FALSE;
break;
default:
useRela = TRUE; // This seems to be the common case
break;
}
for( curr = file->sections; curr != NULL; curr = curr->next ) {
curr->x.elf.pad_amount = 0;
if( curr->first_reloc != NULL ) {
strcpy( buffer, (useRela ? ".rela" : ".rel") );
strcat( buffer, OWLStringText( curr->name ) );
curr->x.elf.relocs_name = OWLStringAdd( file->string_table, buffer );
curr->x.elf.relocs_index = file->next_index++;
}
}
}
static void addSpecialStrings( owl_file_handle file ) {
//*****************************************************
file->x.elf.string_table.name = OWLStringAdd( file->string_table, ".strtab" );
file->x.elf.symbol_table.name = OWLStringAdd( file->string_table, ".symtab" );
}
void ELFFileEmit( owl_file_handle file ) {
//****************************************
prepareRelocSections( file );
writeFileHeader( file );
addSpecialStrings( file );
prepareStringTable( file, &file->x.elf.string_table );
prepareSymbolTable( file, &file->x.elf.symbol_table );
emitSectionHeaders( file );
emitSpecialSection( file, &file->x.elf.string_table );
emitSpecialSection( file, &file->x.elf.symbol_table );
emitSectionData( file );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?