/**************************************************************************** * * This code is Public Domain. * * ======================================================================== * * Description: ELF output routines * ****************************************************************************/ #include #include #include "globals.h" #include "memalloc.h" #include "parser.h" #include "mangle.h" #include "fixup.h" #include "segment.h" #include "extern.h" #include "elf.h" #include "elfspec.h" #include "myassert.h" #if ELF_SUPPORT /* v2.03: create weak externals for ALIAS symbols. * Since the syntax of the ALIAS directive requires * 2 names and, OTOH, the ELF implementation of weak * externals has no "default resolution", the usefullness * of this option is questionable. Additionally, there's * the "EXTERN ()" syntax, which also allows * to define a weak external. */ #define ELFALIAS 0 /* start label is always public for COFF/ELF, no need to add it */ #define ADDSTARTLABEL 0 /* there's no STT_IMPORT type for ELF, it's OW specific */ #define OWELFIMPORT 0 /* use GNU extensions for LD ( 16bit and 8bit relocations ) */ #define GNURELOCS 1 #define MANGLE_BYTES 8 /* extra size required for name decoration */ #define IsWeak( x ) ( x.iscomm == FALSE && x.altname ) /* section attributes for ELF * execute write alloc type *--------------------------------------- * CODE x x progbits * CONST x progbits * DATA x x progbits * BSS x x nobits * STACK x x progbits * others x x progbits * * todo: translate section bits: * - INFO -> SHT_NOTE (added in v2.07) * - DISCARD -> * - SHARED -> * - EXECUTE -> SHF_EXECINSTR * - READ -> * - WRITE -> SHF_WRITE */ /* v2.12: global variables replaced by struct elfmod */ //static uint_32 symindex; /* entries in symbol table */ //static uint_32 start_globals; /* start index globals in symbol table */ //static char *srcname; /* name of source module (name + extension) */ //static bool extused; struct localname { void *next; struct asym *sym; }; enum internal_sections { SHSTRTAB_IDX, SYMTAB_IDX, STRTAB_IDX, NUM_INTSEGS }; struct intsegparm { const char *name; unsigned type; }; /* constant parameters of internal sections; order must match enum internal_sections */ static const struct intsegparm internal_segparms[] = { { ".shstrtab", SHT_STRTAB }, { ".symtab", SHT_SYMTAB }, { ".strtab", SHT_STRTAB }, }; struct intseg { uint_32 size; uint_32 fileoffset; void *data; }; //static struct intseg internal_segs[NUM_INTSEGS]; /* v2.12: all global variables replaced by struct elfmod */ struct elfmod { uint_32 symindex; /* entries in symbol table */ uint_32 start_globals; /* start index globals in symbol table */ char *srcname; /* name of source module (name + extension) */ #if GNURELOCS bool extused; /* gnu extensions used */ #endif struct intseg internal_segs[NUM_INTSEGS]; union { Elf32_Ehdr ehdr32; #if AMD64_SUPPORT Elf64_Ehdr ehdr64; #endif }; }; /* struct to help convert section names in COFF, ELF, PE */ struct conv_section { uint_8 len; uint_8 flags; /* see below */ const char *src; const char *dst; }; enum cvs_flags { CSF_GRPCHK = 1 }; static const struct conv_section cst[] = { { 5, CSF_GRPCHK, "_TEXT", ".text" }, { 5, CSF_GRPCHK, "_DATA", ".data" }, { 5, CSF_GRPCHK, "CONST", ".rodata" }, /* v2.05: .rdata -> .rodata */ { 4, 0, "_BSS", ".bss" } }; /* translate section names: * see cst[] above for details. */ static char *ElfConvertSectionName( const struct asym *sym, char *buffer ) /************************************************************************/ { int i; for ( i = 0; i < sizeof( cst ) / sizeof( cst[0] ); i++ ) { if ( memcmp( sym->name, cst[i].src, cst[i].len ) == 0 ) { if ( sym->name[cst[i].len] == NULLC ) return( (char *)cst[i].dst ); else if ( ( cst[i].flags & CSF_GRPCHK ) && sym->name[cst[i].len] == '$' ) { strcpy( buffer, cst[i].dst ); strcat( buffer, sym->name+cst[i].len ); return( buffer ); } } } return( sym->name ); } /* get number of sections that have relocations */ static int get_num_reloc_sections( void ) /***************************************/ { struct dsym *curr; int num = 0; for( curr = SymTables[TAB_SEG].head; curr; curr = curr->next ) { if ( curr->e.seginfo->FixupList.head ) num++; } return( num ); } /* fill entries in ELF32 symbol table */ static uint_32 set_symtab32( struct elfmod *em, uint_32 entries, struct localname *localshead ) /*********************************************************************************************/ { uint_32 strsize = 1; uint_32 len; uint_8 stt; struct dsym *curr; struct asym *sym; struct localname *localscurr; struct qnode *q; Elf32_Sym *p32; char buffer[MAX_ID_LEN + MANGLE_BYTES + 1]; em->internal_segs[SYMTAB_IDX].size = entries * sizeof( Elf32_Sym ); em->internal_segs[SYMTAB_IDX].data = LclAlloc( em->internal_segs[SYMTAB_IDX].size ); memset( em->internal_segs[SYMTAB_IDX].data, 0, em->internal_segs[SYMTAB_IDX].size ); p32 = (Elf32_Sym *)em->internal_segs[SYMTAB_IDX].data; p32++; /* skip NULL entry */ /* 1. make file entry */ p32->st_name = strsize; /* symbol's name in string table */ strsize += strlen( em->srcname ) + 1; p32->st_value = 0; p32->st_size = 0; p32->st_info = ELF32_ST_INFO( STB_LOCAL, STT_FILE ); /* symbol's type and binding info */ p32->st_shndx = SHN_ABS; /* section index */ p32++; /* 2. make section entries */ for( curr = SymTables[TAB_SEG].head; curr; curr = curr->next ) { //p32->st_name = ?; /* name isn't set */ p32->st_info = ELF32_ST_INFO( STB_LOCAL, STT_SECTION ); p32->st_shndx = GetSegIdx( curr->sym.segment ); p32++; } /* 3. locals */ for ( localscurr = localshead ; localscurr ; localscurr = localscurr->next ) { len = Mangle( localscurr->sym, buffer ); p32->st_name = strsize; curr = (struct dsym *)localscurr->sym->segment; if ( curr && curr->e.seginfo->segtype != SEGTYPE_CODE ) stt = STT_OBJECT; else stt = STT_FUNC; p32->st_info = ELF32_ST_INFO( STB_LOCAL, stt ); p32->st_value = localscurr->sym->offset; #if 1 /* v2.07: changed - to make MT_ABS obsolete */ if ( curr ) p32->st_shndx = GetSegIdx( &curr->sym ); else p32->st_shndx = SHN_ABS; #else if ( localscurr->sym->mem_type == MT_ABS ) p32->st_shndx = SHN_ABS; else p32->st_shndx = GetSegIdx( &curr->sym ); #endif strsize += len + 1; DebugMsg(("set_symtab32, LOCAL: symbol %s, value=%X\n", buffer, p32->st_value)); p32++; } /* 4. externals + communals (+ protos [since v2.01]) */ for( curr = SymTables[TAB_EXT].head ; curr != NULL ;curr = curr->next ) { /* skip "weak" (=unused) externdefs */ if ( curr->sym.iscomm == FALSE && curr->sym.weak == TRUE ) continue; len = Mangle( &curr->sym, buffer ); p32->st_name = strsize; /* for COMMUNALs, store their size in the Value field */ if ( curr->sym.iscomm == TRUE ) { p32->st_info = ELF32_ST_INFO( STB_GLOBAL, STT_COMMON ); p32->st_value = curr->sym.total_size; p32->st_shndx = SHN_COMMON; } else { #if OWELFIMPORT p32->st_info = ( IsWeak( curr->sym ) ? ELF32_ST_INFO( STB_WEAK, STT_IMPORT ) : ELF32_ST_INFO( STB_GLOBAL, STT_IMPORT ) ); #else /* todo: set STT_FUNC for prototypes/code labels??? */ p32->st_info = ( IsWeak( curr->sym ) ? ELF32_ST_INFO( STB_WEAK, STT_NOTYPE ) : ELF32_ST_INFO( STB_GLOBAL, STT_NOTYPE ) ); #endif p32->st_value = curr->sym.offset; /* is always 0 */ p32->st_shndx = SHN_UNDEF; } strsize += len + 1; DebugMsg(("set_symtab32, EXTERNAL: symbol %s, info=%X, shndx=%X, value=%X\n", buffer, p32->st_info, p32->st_shndx, p32->st_value)); p32++; } #if ELFALIAS /* 5. aliases */ for( curr = SymTables[TAB_ALIAS].head ; curr != NULL ;curr = curr->next ) { len = Mangle( &curr->sym, buffer ); p32->st_name = strsize; #if OWELFIMPORT p32->st_info = ELF32_ST_INFO( STB_WEAK, STT_IMPORT ); #else p32->st_info = ELF32_ST_INFO( STB_WEAK, STT_NOTYPE ); #endif p32->st_value = 0; /* is always 0 */ p32->st_shndx = SHN_UNDEF; strsize += len + 1; DebugMsg(("set_symtab32, ALIAS: symbol %s, value=%X\n", buffer, p32->st_value)); p32++; } #endif /* 6. PUBLIC entries */ for ( q = ModuleInfo.g.PubQueue.head; q; q = q->next ) { sym = q->sym; len = Mangle( sym, buffer ); curr = (struct dsym *)sym->segment; if ( curr && curr->e.seginfo->segtype != SEGTYPE_CODE ) stt = STT_OBJECT; else stt = STT_FUNC; p32->st_name = strsize; p32->st_info = ELF32_ST_INFO( STB_GLOBAL, stt ); p32->st_value = sym->offset; #if 1 /* v2.07: changed - to make MT_ABS obsolete */ if ( sym->state == SYM_INTERNAL ) if ( curr ) p32->st_shndx = GetSegIdx( &curr->sym ); else p32->st_shndx = SHN_ABS; else p32->st_shndx = SHN_UNDEF; #else if ( sym->mem_type == MT_ABS ) p32->st_shndx = SHN_ABS; else if ( curr ) p32->st_shndx = GetSegIdx( &curr->sym ); else p32->st_shndx = SHN_UNDEF; #endif strsize += len + 1; DebugMsg(("set_symtab32, PUBLIC+LOCAL: symbol %s, value=%X\n", buffer, p32->st_value)); p32++; } #if ADDSTARTLABEL if ( ModuleInfo.g.start_label ) { len = Mangle( ModuleInfo.g.start_label, buffer ); p32->st_name = strsize; p32->st_info = ELF32_ST_INFO( STB_ENTRY, STT_FUNC ); p32->st_value = ModuleInfo.g.start_label->offset; p32->st_shndx = GetSegIdx( ModuleInfo.g.start_label->segment ); strsize += len + 1; DebugMsg(("set_symtab32, ENTRY: symbol %s, value=%X\n", buffer, p32->st_value)); p32++; } #endif return( strsize ); } #if AMD64_SUPPORT /* fill entries in ELF64 symbol table: typedef struct { uint_32 st_name; // +0 symbol name index into string table uint_8 st_info; // +4 symbol's type and binding attribs. uint_8 st_other; // +5 no meaning yet. uint_16 st_shndx; // +6 section index uint_64 st_value; // +8 symbol "value" uint_64 st_size; // +16 symbol size } Elf64_Sym; */ static uint_32 set_symtab64( struct elfmod *em, uint_32 entries, struct localname *localshead ) /*********************************************************************************************/ { uint_32 strsize = 1; uint_32 len; uint_8 stt; struct dsym *curr; struct asym *sym; struct localname *localscurr; struct qnode *q; Elf64_Sym *p64; char buffer[MAX_ID_LEN + MANGLE_BYTES + 1]; em->internal_segs[SYMTAB_IDX].size = entries * sizeof( Elf64_Sym ); em->internal_segs[SYMTAB_IDX].data = LclAlloc( em->internal_segs[SYMTAB_IDX].size ); memset( em->internal_segs[SYMTAB_IDX].data, 0, em->internal_segs[SYMTAB_IDX].size ); p64 = (Elf64_Sym *)em->internal_segs[SYMTAB_IDX].data; p64++; /* skip NULL entry */ /* 1. make file entry */ p64->st_name = strsize; /* symbol's name in string table */ strsize += strlen( em->srcname ) + 1; p64->st_value = 0; p64->st_size = 0; p64->st_info = ELF64_ST_INFO( STB_LOCAL, STT_FILE ); /* symbol's type and binding info */ p64->st_shndx = SHN_ABS; /* section index */ p64++; /* 2. make section entries */ for( curr = SymTables[TAB_SEG].head; curr; curr = curr->next ) { //p64->st_name = ?; /* name isn't set */ p64->st_info = ELF64_ST_INFO( STB_LOCAL, STT_SECTION ); p64->st_shndx = GetSegIdx( curr->sym.segment ); p64++; } /* 3. locals */ for ( localscurr = localshead ; localscurr ; localscurr = localscurr->next ) { len = Mangle( localscurr->sym, buffer ); p64->st_name = strsize; curr = (struct dsym *)localscurr->sym->segment; if ( curr && curr->e.seginfo->segtype != SEGTYPE_CODE ) stt = STT_OBJECT; else stt = STT_FUNC; p64->st_info = ELF64_ST_INFO( STB_LOCAL, stt ); p64->st_value = localscurr->sym->offset; #if 1 /* v2.07: changed - to make MT_ABS obsolete */ if ( curr ) p64->st_shndx = GetSegIdx( &curr->sym ); else p64->st_shndx = SHN_ABS; #else if ( localscurr->sym->mem_type == MT_ABS ) p64->st_shndx = SHN_ABS; else p64->st_shndx = GetSegIdx( &curr->sym ); #endif strsize += len + 1; DebugMsg(("set_symtab64, LOCAL: symbol %s, value=%" I64_SPEC "X\n", buffer, p64->st_value)); p64++; } /* 4. externals + communals ( + protos [since v2.01]) */ for( curr = SymTables[TAB_EXT].head ; curr != NULL ;curr = curr->next ) { /* skip "weak" (=unused) externdefs */ if ( curr->sym.iscomm == FALSE && curr->sym.weak == TRUE ) continue; len = Mangle( &curr->sym, buffer ); p64->st_name = strsize; /* for COMMUNALs, store their size in the Value field */ if ( curr->sym.iscomm == TRUE ) { p64->st_info = ELF64_ST_INFO( STB_GLOBAL, STT_COMMON ); p64->st_value = curr->sym.total_size; p64->st_shndx = SHN_COMMON; } else { #if OWELFIMPORT p64->st_info = ( IsWeak( curr->sym ) ? ELF64_ST_INFO( STB_WEAK, STT_IMPORT ) : ELF64_ST_INFO( STB_GLOBAL, STT_IMPORT ) ); #else /* todo: set STT_FUNC for prototypes??? */ p64->st_info = ( IsWeak( curr->sym ) ? ELF64_ST_INFO( STB_WEAK, STT_NOTYPE ) : ELF64_ST_INFO( STB_GLOBAL, STT_NOTYPE ) ); #endif p64->st_value = curr->sym.offset; /* is always 0 */ p64->st_shndx = SHN_UNDEF; } strsize += len + 1; DebugMsg(("set_symtab64, EXTERNAL: symbol %s, info=%X, shndx=%X, value=%" I64_SPEC "X\n", buffer, p64->st_info, p64->st_shndx, p64->st_value)); p64++; } #if ELFALIAS /* 5. aliases */ for( curr = SymTables[TAB_ALIAS].head ; curr != NULL ;curr = curr->next ) { len = Mangle( &curr->sym, buffer ); p64->st_name = strsize; #if OWELFIMPORT p64->st_info = ELF64_ST_INFO( STB_WEAK, STT_IMPORT ); #else p64->st_info = ELF64_ST_INFO( STB_WEAK, STT_NOTYPE ); #endif p64->st_value = 0; /* is always 0 */ p64->st_shndx = SHN_UNDEF; strsize += len + 1; DebugMsg(("set_symtab64, ALIASES: symbol %s, value=%" I64_SPEC "X\n", buffer, p64->st_value)); p64++; } #endif /* 6. PUBLIC entries */ for ( q = ModuleInfo.g.PubQueue.head; q; q = q->next ) { sym = q->sym; len = Mangle( sym, buffer ); curr = (struct dsym *)sym->segment; if ( curr && curr->e.seginfo->segtype != SEGTYPE_CODE ) stt = STT_OBJECT; else stt = STT_FUNC; p64->st_name = strsize; p64->st_info = ELF64_ST_INFO( STB_GLOBAL, stt ); p64->st_value = sym->offset; #if 1 /* v2.07: changed - to make MT_ABS obsolete */ if ( sym->state == SYM_INTERNAL ) if ( curr ) p64->st_shndx = GetSegIdx( &curr->sym ); else p64->st_shndx = SHN_ABS; else p64->st_shndx = SHN_UNDEF; #else if ( sym->mem_type == MT_ABS ) p64->st_shndx = SHN_ABS; else if ( curr ) p64->st_shndx = GetSegIdx( &curr->sym ); else p64->st_shndx = SHN_UNDEF; #endif strsize += len + 1; DebugMsg(("set_symtab64, PUBLIC+LOCAL: symbol %s, info=%X, shndx=%X, value=%" I64_SPEC "X\n", buffer, p64->st_info, p64->st_shndx, p64->st_value)); p64++; } #if ADDSTARTLABEL if ( ModuleInfo.g.start_label ) { len = Mangle( ModuleInfo.g.start_label, buffer ); p64->st_name = strsize; p64->st_info = ELF64_ST_INFO( STB_ENTRY, STT_FUNC ); p64->st_value = ModuleInfo.g.start_label->offset; p64->st_shndx = GetSegIdx( ModuleInfo.g.start_label->segment ); strsize += len + 1; DebugMsg(("set_symtab64, ENTRY: symbol %s, value=%" I64_SPEC "X\n", buffer, p64->st_value)); p64++; } #endif return( strsize ); } #endif /* calculate size of .symtab + .strtab section. * set content of these sections. */ static void set_symtab_values( struct elfmod *em ) /************************************************/ { uint_32 strsize; uint_32 entries; struct dsym *curr; //struct asym *sym; struct qnode *q; char *p2; struct { struct localname *head; struct localname *tail; } locals = { NULL, NULL }; struct localname *localscurr; /* symbol table. there is - 1 NULL entry, - 1 entry for the module/file, - 1 entry for each section and - n entries for local symbols - m entries for global symbols */ /* symbol table starts with 1 NULL entry + 1 file entry */ em->symindex = 1 + 1; for( curr = SymTables[TAB_SEG].head; curr; curr = curr->next ) curr->sym.ext_idx = em->symindex++; /* add local symbols to symbol table */ for( curr = SymTables[TAB_SEG].head; curr; curr = curr->next ) { if ( curr->e.seginfo->num_relocs ) { struct fixup *fix = curr->e.seginfo->FixupList.head; for ( ; fix; fix = fix->nextrlc ) { /* if it's not EXTERNAL/PUBLIC, add symbol. */ /* however, if it's an assembly time variable */ /* use a raw section reference */ if ( fix->sym->variable ) { fix->sym = fix->segment_var; } else if ( ( fix->sym->state == SYM_INTERNAL ) && fix->sym->included == FALSE && fix->sym->ispublic == FALSE ) { fix->sym->included = TRUE; localscurr = LclAlloc( sizeof( struct localname ) ); localscurr->next = NULL; localscurr->sym = fix->sym; if (locals.tail) { locals.tail->next = localscurr; locals.tail = localscurr; } else { locals.head = locals.tail = localscurr; } fix->sym->ext_idx = em->symindex++; } } } } DebugMsg(("set_symtab_values: index after sections: %u\n", em->symindex)); em->start_globals = em->symindex; /* count EXTERNs and used EXTERNDEFs (and PROTOs [since v2.01]) */ for( curr = SymTables[TAB_EXT].head ; curr != NULL ;curr = curr->next ) { if ( curr->sym.iscomm == FALSE && curr->sym.weak == TRUE ) continue; curr->sym.ext_idx = em->symindex++; } DebugMsg(("set_symtab_values: index after EXTERNALs: %u\n", em->symindex)); #if ELFALIAS /* count aliases */ for( curr = SymTables[TAB_ALIAS].head ; curr != NULL ;curr = curr->next ) { curr->sym.idx = em->symindex++; } DebugMsg(("set_symtab_values: index after ALIASES: %u\n", em->symindex)); #endif /* count publics */ for ( q = ModuleInfo.g.PubQueue.head; q; q = q->next ) { q->sym->ext_idx = em->symindex++; } DebugMsg(("set_symtab_values: index after PUBLICs: %u\n", em->symindex)); /* size of symbol table is defined */ entries = em->symindex; #if ADDSTARTLABEL if ( ModuleInfo.g.start_label ) entries++; #endif #if AMD64_SUPPORT if ( ModuleInfo.defOfssize == USE64 ) strsize = set_symtab64( em, entries, locals.head ); else #endif strsize = set_symtab32( em, entries, locals.head ); /* generate the string table */ DebugMsg(("set_symtab_values: creating string table, size=%X\n", strsize)); em->internal_segs[STRTAB_IDX].size = strsize; em->internal_segs[STRTAB_IDX].data = LclAlloc( strsize ); memset( em->internal_segs[STRTAB_IDX].data, 0, strsize ); p2 = em->internal_segs[STRTAB_IDX].data; *p2++ = NULLC; strcpy( p2, em->srcname ); p2 += strlen( p2 ) + 1; for ( localscurr = locals.head ; localscurr ; localscurr = localscurr->next ) { p2 += Mangle( localscurr->sym, p2 ) + 1; } for( curr = SymTables[TAB_EXT].head ; curr != NULL ;curr = curr->next ) { if ( curr->sym.iscomm == FALSE && curr->sym.weak == TRUE ) continue; p2 += Mangle( &curr->sym, p2 ) + 1; } #if ELFALIAS for( curr = SymTables[TAB_ALIAS].head ; curr != NULL ;curr = curr->next ) { p2 += Mangle( &curr->sym, p2 ) + 1; } #endif for ( q = ModuleInfo.g.PubQueue.head; q; q = q->next ) { p2 += Mangle( q->sym, p2 ) + 1; } #if ADDSTARTLABEL if ( ModuleInfo.g.start_label ) { Mangle( ModuleInfo.g.start_label, p2 ); } #endif DebugMsg(("set_symtab_values: exit, symindex=%u\n", em->symindex )); return; } /* set content + size of .shstrtab section. * this section contains the names of all sections. * three groups of sections are handled: * - sections defined in the program * - ELF internal sections * - relocation sections * alloc .shstrtab */ static void set_shstrtab_values( struct elfmod *em ) /**************************************************/ { int i; struct dsym *curr; char *p; unsigned int size = 1; /* the first byte at offset 0 is the NULL section name */ char buffer[MAX_ID_LEN+1]; /* get size of section names defined in the program & relocation sections ) */ for( curr = SymTables[TAB_SEG].head; curr; curr = curr->next ) { /* v2.07: ALIAS name defined? */ p = ( curr->e.seginfo->aliasname ? curr->e.seginfo->aliasname : ElfConvertSectionName( &curr->sym, buffer ) ); size += strlen( p ) + 1; if ( curr->e.seginfo->FixupList.head ) size += strlen( p ) + #if AMD64_SUPPORT (( ModuleInfo.defOfssize == USE64 ) ? sizeof(".rela") : sizeof(".rel")); #else sizeof(".rel"); #endif } /* get internal section name sizes */ for ( i = 0; i < NUM_INTSEGS; i++ ) { size += strlen( internal_segparms[i].name ) + 1; } em->internal_segs[SHSTRTAB_IDX].size = size; /* size is known, now alloc .shstrtab data buffer and fill it */ em->internal_segs[SHSTRTAB_IDX].data = LclAlloc( size ); p = (char *)em->internal_segs[SHSTRTAB_IDX].data; *p++ = NULLC; /* NULL section name */ /* 1. names of program sections */ for( curr = SymTables[TAB_SEG].head; curr; curr = curr->next ) { strcpy( p, curr->e.seginfo->aliasname ? curr->e.seginfo->aliasname : ElfConvertSectionName( &curr->sym, buffer ) ); p += strlen( p ) + 1; } /* 2. names of internal sections */ for ( i = 0; i < NUM_INTSEGS; i++ ) { strcpy( p, internal_segparms[i].name ); p += strlen( p ) + 1; } /* 3. names of "relocation" sections */ for( curr = SymTables[TAB_SEG].head; curr; curr = curr->next ) { if ( curr->e.seginfo->FixupList.head ) { #if AMD64_SUPPORT strcpy( p, (( ModuleInfo.defOfssize == USE64 ) ? ".rela": ".rel") ); #else strcpy( p, ".rel" ); #endif p += strlen( p ); strcpy( p, curr->e.seginfo->aliasname ? curr->e.seginfo->aliasname : ElfConvertSectionName( &curr->sym, buffer ) ); p += strlen( p ) + 1; } } /**/myassert( size == p - (char *)em->internal_segs[SHSTRTAB_IDX].data ); DebugMsg(("set_shstrtab_values: size=%X\n", size)); return; } static unsigned int get_relocation_count( struct dsym *curr ) /***********************************************************/ { unsigned relocs; struct fixup *fix; for ( relocs = 0, fix = curr->e.seginfo->FixupList.head; fix ; fix = fix->nextrlc, relocs++ ); return( relocs ); } static unsigned int Get_Alignment( struct dsym *curr ) /****************************************************/ { if ( curr->e.seginfo->alignment == MAX_SEGALIGNMENT ) return( 0 ); return( 1 << curr->e.seginfo->alignment ); } /* write ELF32 section table. * fileoffset: start of section data ( behind elf header and section table ) * there are 3 groups of sections to handle: * - the sections defined in the module * - the internal ELF sections ( .shstrtab, .symtab, .strtab ) * - the 'relocation' sections */ static int elf_write_section_table32( struct module_info *modinfo, struct elfmod *em, uint_32 fileoffset ) /********************************************************************************************************/ { int i; struct dsym *curr; uint_8 *p; //uint_32 fileoffset; Elf32_Shdr shdr32; DebugMsg(("elf_write_section_table32( fileofs=%X ): enter\n", fileoffset )); //fileoffset = sizeof(Elf64_Ehdr) + ehdr->e_shnum * ehdr->e_shentsize; fileoffset = (fileoffset + 0xF) & ~0xF; /* set contents and size of internal .shstrtab section */ set_shstrtab_values( em ); /* write the NULL entry */ memset( &shdr32, 0, sizeof( shdr32) ); if ( fwrite( &shdr32, 1, sizeof(shdr32), CurrFile[OBJ] ) != sizeof(shdr32) ) /* write the empty NULL entry */ WriteError(); /* use p to scan strings (=section names) of .shstrtab */ p = (uint_8 *)em->internal_segs[SHSTRTAB_IDX].data; p++; /* skip 'name' of NULL entry */ /* write the section headers defined in the module, */ for( curr = SymTables[TAB_SEG].head; curr; curr = curr->next ) { memset( &shdr32, 0, sizeof(shdr32) ); shdr32.sh_name = p - (uint_8 *)em->internal_segs[SHSTRTAB_IDX].data; p += strlen( (char *)p ) + 1; if ( curr->e.seginfo->info == TRUE ) { /* v2.07:added; v2.12: highest priority */ shdr32.sh_type = SHT_NOTE; shdr32.sh_flags = 0; } else { shdr32.sh_type = ( curr->e.seginfo->segtype != SEGTYPE_BSS ? SHT_PROGBITS : SHT_NOBITS ); if ( curr->e.seginfo->segtype == SEGTYPE_CODE ) { shdr32.sh_flags = SHF_EXECINSTR | SHF_ALLOC; } else if ( curr->e.seginfo->readonly == TRUE ) { shdr32.sh_flags = SHF_ALLOC; } else if ( curr->e.seginfo->clsym && strcmp( curr->e.seginfo->clsym->name, "CONST" ) == 0 ) { shdr32.sh_flags = SHF_ALLOC; /* v2.07: added */ } else { shdr32.sh_flags = SHF_WRITE | SHF_ALLOC; } } #if 0 /* todo: translate values in field to * elf section flags. */ if ( curr->e.seginfo->characteristics == ??? ) { } #endif shdr32.sh_addr = 0; /* v2.12: the sh_offset field holds the file position, even for SHT_NOBITS */ //if ( shdr32.sh_type != SHT_NOBITS ) { shdr32.sh_offset = fileoffset; /* start of section in file */ curr->e.seginfo->fileoffset = fileoffset; /* save the offset in the segment */ //} /* v2.07: set size for all sections, including .bss */ shdr32.sh_size = curr->sym.max_offset; shdr32.sh_link = 0; shdr32.sh_info = 0; shdr32.sh_addralign = Get_Alignment( curr ); shdr32.sh_entsize = 0; if ( fwrite( &shdr32, 1, sizeof(shdr32), CurrFile[OBJ] ) != sizeof(shdr32) ) WriteError(); curr->e.seginfo->num_relocs = get_relocation_count( curr ); /* v2.12: don't adjust fileoffset for SHT_NOBITS sections. * it didn't cause fatal damage previously, but made the * object module unnecessary large. */ if ( shdr32.sh_type != SHT_NOBITS ) { fileoffset += shdr32.sh_size; fileoffset = (fileoffset + 0xF) & ~0xF; } DebugMsg(("elf_write_section_table32(%s): ofs=%X size=%X numrelocs=%u\n", curr->sym.name, shdr32.sh_offset, shdr32.sh_size, curr->e.seginfo->num_relocs)); } /* set size and contents of .symtab and .strtab sections */ set_symtab_values( em ); /* write headers of internal sections */ for ( i = 0; i < NUM_INTSEGS; i++ ) { shdr32.sh_name = p - (uint_8 *)em->internal_segs[SHSTRTAB_IDX].data; p += strlen( (char *)p ) + 1; shdr32.sh_type = internal_segparms[i].type; shdr32.sh_flags = 0; shdr32.sh_offset = fileoffset; /* start of section in file */ em->internal_segs[i].fileoffset = fileoffset; shdr32.sh_size = em->internal_segs[i].size; /* section .symtab is special */ if ( i == SYMTAB_IDX ) { shdr32.sh_link = 1 + modinfo->g.num_segs + STRTAB_IDX; shdr32.sh_info = em->start_globals; shdr32.sh_addralign = 4; shdr32.sh_entsize = sizeof( Elf32_Sym ); } else { shdr32.sh_link = 0; shdr32.sh_info = 0; shdr32.sh_addralign = 1; shdr32.sh_entsize = 0; } if ( fwrite( &shdr32, 1, sizeof( shdr32 ), CurrFile[OBJ] ) != sizeof( shdr32 ) ) WriteError(); fileoffset += shdr32.sh_size; fileoffset = (fileoffset + 0xF) & ~0xF; DebugMsg(("elf_write_section_table32(%s): ofs=%X size=%X\n", internal_segparms[i].name, shdr32.sh_offset, shdr32.sh_size)); } /* write headers of reloc sections */ for( curr = SymTables[TAB_SEG].head; curr; curr = curr->next ) { if ( curr->e.seginfo->FixupList.head == NULL ) continue; memset( &shdr32, 0, sizeof( shdr32 ) ); shdr32.sh_name = p - (uint_8 *)em->internal_segs[SHSTRTAB_IDX].data; p += strlen( (char *)p ) + 1; shdr32.sh_type = SHT_REL; shdr32.sh_flags = 0; shdr32.sh_addr = 0; shdr32.sh_offset = fileoffset; /* start of section in file */ /* save the file offset in the slot reserved for ELF relocs */ curr->e.seginfo->reloc_offset = fileoffset; /* size of section in file */ shdr32.sh_size = curr->e.seginfo->num_relocs * sizeof( Elf32_Rel ); shdr32.sh_link = 1 + modinfo->g.num_segs + SYMTAB_IDX; /* set info to the src section index */ shdr32.sh_info = GetSegIdx( curr->sym.segment ); shdr32.sh_addralign = 4; shdr32.sh_entsize = sizeof( Elf32_Rel ); if ( fwrite( &shdr32, 1, sizeof( shdr32 ), CurrFile[OBJ] ) != sizeof( shdr32 ) ) WriteError(); fileoffset += shdr32.sh_size; fileoffset = (fileoffset + 0xF) & ~0xF; DebugMsg(("elf_write_section_table32(%s): relocs, ofs=%X size=%X\n", curr->sym.name, shdr32.sh_offset, shdr32.sh_size)); } DebugMsg(("elf_write_section_table32: exit, final fileofs=%X\n", fileoffset )); return( NOT_ERROR ); } #if AMD64_SUPPORT /* write ELF64 section table. */ static int elf_write_section_table64( struct module_info *modinfo, struct elfmod *em, uint_32 fileoffset ) /********************************************************************************************************/ { int i; struct dsym *curr; uint_8 *p; //uint_32 fileoffset; Elf64_Shdr shdr64; DebugMsg(("elf_write_section_table64( fileofs=%X ): enter\n", fileoffset )); //fileoffset = sizeof(Elf64_Ehdr) + ehdr->e_shnum * ehdr->e_shentsize; fileoffset = (fileoffset + 0xF) & ~0xF; /* set contents and size of internal .shstrtab section */ set_shstrtab_values( em ); /* write the NULL entry */ memset( &shdr64, 0, sizeof( shdr64) ); if ( fwrite( &shdr64, 1, sizeof(shdr64), CurrFile[OBJ] ) != sizeof(shdr64) ) /* write the empty NULL entry */ WriteError(); /* use p to scan strings (=section names) of .shstrtab */ p = (uint_8 *)em->internal_segs[SHSTRTAB_IDX].data; p++; /* skip 'name' of NULL entry */ /* write the section headers defined in the module */ for( curr = SymTables[TAB_SEG].head; curr; curr = curr->next ) { memset( &shdr64, 0, sizeof(shdr64) ); shdr64.sh_name = p - (uint_8 *)em->internal_segs[SHSTRTAB_IDX].data; p += strlen( (char *)p ) + 1; if ( curr->e.seginfo->info == TRUE ) { /* v2.07:added; v2.12: highest priority */ shdr64.sh_type = SHT_NOTE; shdr64.sh_flags = 0; } else { shdr64.sh_type = ( curr->e.seginfo->segtype != SEGTYPE_BSS ? SHT_PROGBITS : SHT_NOBITS ); if ( curr->e.seginfo->segtype == SEGTYPE_CODE ) { shdr64.sh_flags = SHF_EXECINSTR | SHF_ALLOC; } else if ( curr->e.seginfo->readonly == TRUE ) { shdr64.sh_flags = SHF_ALLOC; } else if ( curr->e.seginfo->clsym && strcmp( curr->e.seginfo->clsym->name, "CONST" ) == 0 ) { shdr64.sh_flags = SHF_ALLOC; /* v2.07: added */ } else { shdr64.sh_flags = SHF_WRITE | SHF_ALLOC; } } #if 0 /* todo: translate values in field to * elf section flags. */ if ( curr->e.seginfo->characteristics == ??? ) { } #endif shdr64.sh_addr = 0; /* v2.12: the sh_offset field holds the file position, even for SHT_NOBITS */ //if ( shdr64.sh_type != SHT_NOBITS ) { shdr64.sh_offset = fileoffset; /* start of section in file */ curr->e.seginfo->fileoffset = fileoffset; /* save the offset in the segment */ //} /* v2.07: set size for all sections, including .bss */ shdr64.sh_size = curr->sym.max_offset; shdr64.sh_link = 0; shdr64.sh_info = 0; shdr64.sh_addralign = Get_Alignment( curr ); shdr64.sh_entsize = 0; if ( fwrite( &shdr64, 1, sizeof(shdr64), CurrFile[OBJ] ) != sizeof(shdr64) ) WriteError(); curr->e.seginfo->num_relocs = get_relocation_count( curr ); /* v2.12: don't adjust fileoffset for SHT_NOBITS sections */ if ( shdr64.sh_type != SHT_NOBITS ) { fileoffset += shdr64.sh_size; fileoffset = (fileoffset + 0xF) & ~0xF; } DebugMsg(("elf_write_section_table64(%s): ofs=%" I64_SPEC "X size=%" I64_SPEC "X numrelocs=%u\n", curr->sym.name, shdr64.sh_offset, shdr64.sh_size, curr->e.seginfo->num_relocs)); } /* set size and contents of .symtab and .strtab sections */ set_symtab_values( em ); /* write headers of internal sections */ for ( i = 0; i < NUM_INTSEGS; i++ ) { shdr64.sh_name = p - (uint_8 *)em->internal_segs[SHSTRTAB_IDX].data; p += strlen( (char *)p ) + 1; shdr64.sh_type = internal_segparms[i].type; shdr64.sh_flags = 0; shdr64.sh_offset = fileoffset; /* start of section in file */ em->internal_segs[i].fileoffset = fileoffset; shdr64.sh_size = em->internal_segs[i].size; /* section .symtab is special */ if ( i == SYMTAB_IDX ) { shdr64.sh_link = 1 + modinfo->g.num_segs + STRTAB_IDX; shdr64.sh_info = em->start_globals; shdr64.sh_addralign = 4; shdr64.sh_entsize = sizeof( Elf64_Sym ); } else { shdr64.sh_link = 0; shdr64.sh_info = 0; shdr64.sh_addralign = 1; shdr64.sh_entsize = 0; } if ( fwrite( &shdr64, 1, sizeof( shdr64 ), CurrFile[OBJ] ) != sizeof( shdr64 ) ) WriteError(); fileoffset += shdr64.sh_size; fileoffset = (fileoffset + 0xF) & ~0xF; DebugMsg(("elf_write_section_table64(%s): ofs=%" I64_SPEC "X size=%" I64_SPEC "X\n", internal_segparms[i].name, shdr64.sh_offset, shdr64.sh_size)); } /* write headers of reloc sections */ for( curr = SymTables[TAB_SEG].head; curr; curr = curr->next ) { if ( curr->e.seginfo->FixupList.head == NULL ) continue; memset( &shdr64, 0, sizeof(shdr64) ); shdr64.sh_name = p - (uint_8 *)em->internal_segs[SHSTRTAB_IDX].data; p += strlen( (char *)p ) + 1; shdr64.sh_type = SHT_RELA; /* v2.05: changed REL to RELA */ shdr64.sh_flags = 0; shdr64.sh_addr = 0; shdr64.sh_offset = fileoffset; /* start of section in file */ /* save the file offset in the slot reserved for ELF relocs */ curr->e.seginfo->reloc_offset = fileoffset; /* size of section in file */ shdr64.sh_size = curr->e.seginfo->num_relocs * sizeof( Elf64_Rela ); shdr64.sh_link = 1 + modinfo->g.num_segs + SYMTAB_IDX; /* set info to the src section index */ shdr64.sh_info = GetSegIdx( curr->sym.segment ); shdr64.sh_addralign = 4; shdr64.sh_entsize = sizeof( Elf64_Rela ); if ( fwrite( &shdr64, 1, sizeof( shdr64 ), CurrFile[OBJ] ) != sizeof( shdr64 ) ) WriteError(); fileoffset += shdr64.sh_size; fileoffset = (fileoffset + 0xF) & ~0xF; DebugMsg(("elf_write_section_table64(%s): relocs, ofs=%" I64_SPEC "X size=%" I64_SPEC "X\n", curr->sym.name, shdr64.sh_offset, shdr64.sh_size)); } DebugMsg(("elf_write_section_table64: exit, final fileofs=%X\n", fileoffset )); return( NOT_ERROR ); } #endif /* write 1 section's relocations (32-bit) */ static void write_relocs32( struct elfmod *em, struct dsym *curr ) /****************************************************************/ { uint_8 elftype; struct fixup *fixup; Elf32_Rel reloc32; DebugMsg(("write_relocs32: enter\n")); for ( fixup = curr->e.seginfo->FixupList.head; fixup; fixup = fixup->nextrlc ) { reloc32.r_offset = fixup->locofs; switch ( fixup->type ) { case FIX_OFF32: elftype = R_386_32; break; case FIX_RELOFF32: elftype = R_386_PC32; break; //case FIX_???: elftype = R_386_GOT32; break; //case FIX_???: elftype = R_386_PLT32; break; //case FIX_???: elftype = R_386_COPY; break; //case FIX_???: elftype = R_386_GLOB_DAT; break; //case FIX_???: elftype = R_386_JMP_SLOT; break; case FIX_OFF32_IMGREL: elftype = R_386_RELATIVE; break; //case FIX_???: elftype = R_386_GOTOFF; break; //case FIX_???: elftype = R_386_GOTPC; break; #if GNURELOCS case FIX_OFF16: em->extused = TRUE; elftype = R_386_16; break; case FIX_RELOFF16: em->extused = TRUE; elftype = R_386_PC16; break; case FIX_OFF8: em->extused = TRUE; elftype = R_386_8; break; case FIX_RELOFF8: em->extused = TRUE; elftype = R_386_PC8; break; #endif default: DebugMsg(("write_relocs32(): unhandled reloc loc=%X type=%u idx=%u sym=%s\n", fixup->locofs, fixup->type, fixup->sym->ext_idx, fixup->sym->name)); elftype = R_386_NONE; if ( fixup->type < FIX_LAST ) { EmitErr( INVALID_FIXUP_TYPE, ModuleInfo.fmtopt->formatname, fixup->type, curr->sym.name, fixup->locofs ); } else EmitErr( UNKNOWN_FIXUP_TYPE, fixup->type, curr->sym.name, fixup->locofs ); } /* the low 8 bits of info are type */ /* the high 24 bits are symbol table index */ reloc32.r_info = ELF32_R_INFO( fixup->sym->ext_idx, elftype ); if ( fwrite( &reloc32, 1, sizeof(reloc32), CurrFile[OBJ] ) != sizeof(reloc32) ) WriteError(); } DebugMsg(("write_relocs32: exit\n")); return; } #if AMD64_SUPPORT /* write 1 section's relocations (64-bit) */ static void write_relocs64( struct dsym *curr ) /*********************************************/ { uint_8 elftype; struct fixup *fixup; Elf64_Rela reloc64; /* v2.05: changed to Rela */ DebugMsg(("write_relocs64: enter\n")); for ( fixup = curr->e.seginfo->FixupList.head; fixup; fixup = fixup->nextrlc ) { unsigned symidx = fixup->sym->ext_idx; reloc64.r_offset = fixup->locofs; /* v2.07: addend wasn't handled correctly. * Also note the type cast for fixup.offset - * r_addend has type int_64, while fixup.offset has type uint_32! */ //reloc64.r_addend = fixup->offset; /* the following line depends on what's done in store_fixup(). * if the inline addend is set to 0 there, the fixup->offset * must be used in the calculation ( it's 32-bit only!!! ). */ //reloc64.r_addend = (int_32)fixup->offset - fixup->addbytes; /* * if the inline addend is not touched in store_fixup(), * we just have to use the addbytes field. */ reloc64.r_addend = - fixup->addbytes; DebugMsg(("write_relocs64(): reloc loc=%X type=%u idx=%u sym=%s ofs=%X addbyt=%u\n", fixup->locofs, fixup->type, fixup->sym->ext_idx, fixup->sym->name, fixup->offset, fixup->addbytes )); switch ( fixup->type ) { case FIX_RELOFF32: #if 0 /* v2.07: activate if the section's index is to be used as symtab ref */ if ( fixup->sym->segment != &curr->sym ) { //printf("PC-relative fixup to another section: %s\n", fixup->sym->name ); reloc64.r_addend += fixup->sym->offset; symidx = fixup->sym->segment->ext_idx; } #endif elftype = R_X86_64_PC32; break; case FIX_OFF64: elftype = R_X86_64_64; break; //case FIX_???: elftype = R_X86_64_GOT32; break; //case FIX_???: elftype = R_X86_64_PLT32; break; //case FIX_???: elftype = R_X86_64_COPY; break; //case FIX_???: elftype = R_X86_64_GLOB_DAT; break; //case FIX_???: elftype = R_X86_64_JMP_SLOT; break; case FIX_OFF32_IMGREL: elftype = R_X86_64_RELATIVE; break; //case FIX_???: elftype = R_X86_64_GOTPCREL; break; case FIX_OFF32: elftype = R_X86_64_32; break; //case FIX_???: elftype = R_X86_64_32S; break; case FIX_OFF16: elftype = R_X86_64_16; break; case FIX_RELOFF16: elftype = R_X86_64_PC16; break; case FIX_OFF8: elftype = R_X86_64_8; break; case FIX_RELOFF8: elftype = R_X86_64_PC8; break; //case FIX_???: elftype = R_X86_64_DPTMOD64; break; //case FIX_???: elftype = R_X86_64_DPTOFF64; break; //case FIX_???: elftype = R_X86_64_TPOFF64; break; //case FIX_???: elftype = R_X86_64_TLSGD; break; //case FIX_???: elftype = R_X86_64_TLSLD; break; //case FIX_???: elftype = R_X86_64_DPTOFF32; break; //case FIX_???: elftype = R_X86_64_GOTTPOFF; break; //case FIX_???: elftype = R_X86_64_TPOFF32; break; //case FIX_???: elftype = R_X86_64_PC64; break; //case FIX_???: elftype = R_X86_64_GOTOFF64; break; //case FIX_???: elftype = R_X86_64_GOTPC32; break; //case FIX_???: elftype = R_X86_64_SIZE32; break; //case FIX_???: elftype = R_X86_64_SIZE64; break; default: DebugMsg(("write_relocs64(): unhandled reloc loc=%X type=%u idx=%u sym=%s\n", fixup->locofs, fixup->type, fixup->sym->ext_idx, fixup->sym->name)); elftype = R_X86_64_NONE; if ( fixup->type < FIX_LAST ) { EmitErr( INVALID_FIXUP_TYPE, ModuleInfo.fmtopt->formatname, fixup->type, curr->sym.name, fixup->locofs ); } else EmitErr( UNKNOWN_FIXUP_TYPE, fixup->type, curr->sym.name, fixup->locofs ); } /* the low 8 bits of info are type */ /* the high 24 bits are symbol table index */ reloc64.r_info = ELF64_R_INFO( symidx, elftype ); if ( fwrite( &reloc64, 1, sizeof( reloc64 ), CurrFile[OBJ] ) != sizeof(reloc64) ) WriteError(); } DebugMsg(("write_relocs64: exit\n")); return; } #endif /* write section contents and fixups */ static ret_code elf_write_data( struct module_info *modinfo, struct elfmod *em ) /******************************************************************************/ { struct dsym *curr; //int seg_index; //uint_32 offset = 0; uint_32 size; int i; DebugMsg(("elf_write_data: enter\n")); for( curr = SymTables[TAB_SEG].head; curr; curr = curr->next ) { size = curr->sym.max_offset - curr->e.seginfo->start_loc; DebugMsg(("elf_write_data(%s): program data at ofs=%X, size=%X\n", curr->sym.name, curr->e.seginfo->fileoffset, size )); if ( curr->e.seginfo->segtype != SEGTYPE_BSS && size != 0 ) { fseek( CurrFile[OBJ], curr->e.seginfo->fileoffset + curr->e.seginfo->start_loc, SEEK_SET ); /**/myassert( curr->e.seginfo->CodeBuffer ); if ( fwrite( curr->e.seginfo->CodeBuffer, 1, size, CurrFile[OBJ] ) != size ) WriteError(); } } /* write internal sections */ for ( i = 0; i < NUM_INTSEGS; i++ ) { if ( em->internal_segs[i].data ) { DebugMsg(("elf_write_data(%s): internal at ofs=%X, size=%X\n", internal_segparms[i].name, em->internal_segs[i].fileoffset, em->internal_segs[i].size)); fseek( CurrFile[OBJ], em->internal_segs[i].fileoffset, SEEK_SET ); if ( fwrite( em->internal_segs[i].data, 1, em->internal_segs[i].size, CurrFile[OBJ] ) != em->internal_segs[i].size ) WriteError(); } } /* write reloc sections content */ for( curr = SymTables[TAB_SEG].head; curr; curr = curr->next ) { if ( curr->e.seginfo->num_relocs ) { DebugMsg(("elf_write_data(%s): relocs at ofs=%X, size=%X\n", curr->sym.name, curr->e.seginfo->reloc_offset, curr->e.seginfo->num_relocs * sizeof(Elf32_Rel))); fseek( CurrFile[OBJ], curr->e.seginfo->reloc_offset, SEEK_SET ); #if AMD64_SUPPORT if ( modinfo->defOfssize == USE64 ) write_relocs64( curr ); else #endif write_relocs32( em, curr ); } } #if GNURELOCS if ( em->extused ) { EmitWarn( 2, ELF_GNU_EXTENSIONS_USED ); } #endif DebugMsg(("elf_write_data: exit\n")); return( NOT_ERROR ); } /* write ELF module */ static ret_code elf_write_module( struct module_info *modinfo ) /*************************************************************/ { //struct dsym *dir; struct elfmod em; DebugMsg(("elf_write_module: enter\n")); memset( &em, 0, sizeof( em ) ); em.srcname = CurrFName[ASM]; #if 1 /* the path part is stripped. todo: check if this is ok to do */ em.srcname += strlen( em.srcname ); while ( em.srcname > CurrFName[ASM] && *(em.srcname-1) != '/' && *(em.srcname-1) != '\\') em.srcname--; #endif /* position at 0 ( probably unnecessary, since there were no writes yet ) */ fseek( CurrFile[OBJ], 0, SEEK_SET ); switch ( modinfo->defOfssize ) { #if AMD64_SUPPORT case USE64: memcpy( &em.ehdr64.e_ident, ELF_SIGNATURE, ELF_SIGNATURE_LEN ); em.ehdr64.e_ident[EI_CLASS] = ELFCLASS64; em.ehdr64.e_ident[EI_DATA] = ELFDATA2LSB; em.ehdr64.e_ident[EI_VERSION] = EV_CURRENT; em.ehdr64.e_ident[EI_OSABI] = modinfo->elf_osabi; /* v2.07: set abiversion to 0 */ //ehdr64.e_ident[EI_ABIVERSION] = EV_CURRENT; em.ehdr64.e_ident[EI_ABIVERSION] = 0; em.ehdr64.e_type = ET_REL; /* file type */ em.ehdr64.e_machine = EM_X86_64; em.ehdr64.e_version = EV_CURRENT; em.ehdr64.e_entry = 0; /* no entry for relocatable objects */ em.ehdr64.e_phoff = 0; /* no progheaders for relocatable objects */ em.ehdr64.e_shoff = sizeof( em.ehdr64 ); em.ehdr64.e_flags = 0; em.ehdr64.e_ehsize = sizeof( em.ehdr64 ); em.ehdr64.e_phentsize = 0; /* no progheaders for relocatable objects */ em.ehdr64.e_phnum = 0; em.ehdr64.e_shentsize = sizeof( Elf64_Shdr ); /* calculate # of sections. Add the following internal sections: - 1 NULL entry - 1 .shstrtab - 1 .symtab - 1 .strtab - n .rela sections */ em.ehdr64.e_shnum = 1 + modinfo->g.num_segs + 3 + get_num_reloc_sections(); em.ehdr64.e_shstrndx = 1 + modinfo->g.num_segs + SHSTRTAB_IDX; /* set index of .shstrtab section */ if ( fwrite( &em.ehdr64, 1, sizeof( em.ehdr64 ), CurrFile[OBJ] ) != sizeof( em.ehdr64 ) ) WriteError(); elf_write_section_table64( modinfo, &em, sizeof( Elf64_Ehdr ) + em.ehdr64.e_shnum * em.ehdr64.e_shentsize ); break; #endif default: memcpy( &em.ehdr32.e_ident, ELF_SIGNATURE, ELF_SIGNATURE_LEN ); em.ehdr32.e_ident[EI_CLASS] = ELFCLASS32; em.ehdr32.e_ident[EI_DATA] = ELFDATA2LSB; em.ehdr32.e_ident[EI_VERSION] = EV_CURRENT; em.ehdr32.e_ident[EI_OSABI] = modinfo->elf_osabi; /* v2.07: set abiversion to 0 */ //ehdr32.e_ident[EI_ABIVERSION] = EV_CURRENT; em.ehdr32.e_ident[EI_ABIVERSION] = 0; em.ehdr32.e_type = ET_REL; /* file type */ em.ehdr32.e_machine = EM_386; em.ehdr32.e_version = EV_CURRENT; em.ehdr32.e_entry = 0; /* no entry for relocatable objects */ em.ehdr32.e_phoff = 0; /* no progheaders for relocatable objects */ em.ehdr32.e_shoff = sizeof( em.ehdr32 ); em.ehdr32.e_flags = 0; em.ehdr32.e_ehsize = sizeof( em.ehdr32 ); em.ehdr32.e_phentsize = 0; /* no progheaders for relocatable objects */ em.ehdr32.e_phnum = 0; em.ehdr32.e_shentsize = sizeof( Elf32_Shdr ); /* calculate # of sections. Add the following internal sections: - 1 NULL entry - 1 .shstrtab - 1 .symtab - 1 .strtab - n .rel entries */ em.ehdr32.e_shnum = 1 + modinfo->g.num_segs + 3 + get_num_reloc_sections(); em.ehdr32.e_shstrndx = 1 + modinfo->g.num_segs + SHSTRTAB_IDX; /* set index of .shstrtab section */ if ( fwrite( &em.ehdr32, 1, sizeof( em.ehdr32 ), CurrFile[OBJ] ) != sizeof( em.ehdr32 ) ) WriteError(); elf_write_section_table32( modinfo, &em, sizeof( Elf32_Ehdr ) + em.ehdr32.e_shnum * em.ehdr32.e_shentsize ); }; elf_write_data( modinfo, &em ); DebugMsg(("elf_write_module: exit\n")); return( NOT_ERROR ); } /* format-specific init. * called once per module. */ void elf_init( struct module_info *modinfo ) /******************************************/ { modinfo->elf_osabi = ELFOSABI_LINUX; modinfo->g.WriteModule = elf_write_module; #if 0 printf("size Elf_Ehdr: %2u - %2u\n", sizeof(Elf32_Ehdr), sizeof(Elf64_Ehdr)); printf("size Elf_Shdr: %2u - %2u\n", sizeof(Elf32_Shdr), sizeof(Elf64_Shdr)); printf("size Elf_Sym : %2u - %2u\n", sizeof(Elf32_Sym ), sizeof(Elf64_Sym )); printf("size Elf_Rel : %2u - %2u\n", sizeof(Elf32_Rel ), sizeof(Elf64_Rel )); printf("size Elf_Rela: %2u - %2u\n", sizeof(Elf32_Rela), sizeof(Elf64_Rela)); #endif return; } #endif