ST_FN void pe_add_runtime_ex(TCCState *s1, struct pe_info *pe) { const char *start_symbol; unsigned long addr = 0; int pe_type = 0; if (find_elf_sym(symtab_section, "_WinMain@16")) pe_type = PE_GUI; else if (TCC_OUTPUT_DLL == s1->output_type) { pe_type = PE_DLL; /* need this for 'tccelf.c:relocate_section()' */ s1->output_type = TCC_OUTPUT_EXE; } start_symbol = TCC_OUTPUT_MEMORY == s1->output_type ? PE_GUI == pe_type ? "_runwinmain" : NULL : PE_DLL == pe_type ? "__dllstart@12" : PE_GUI == pe_type ? "_winstart" : "_start" ; /* grab the startup code from libtcc1 */ if (start_symbol) add_elf_sym(symtab_section, 0, 0, ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, SHN_UNDEF, start_symbol); if (0 == s1->nostdlib) { tcc_add_library(s1, "tcc1"); #ifdef __CYGWIN__ tcc_add_library(s1, "cygwin1"); #else tcc_add_library(s1, "msvcrt"); #endif tcc_add_library(s1, "kernel32"); if (PE_DLL == pe_type || PE_GUI == pe_type) { tcc_add_library(s1, "user32"); tcc_add_library(s1, "gdi32"); } } if (start_symbol) { addr = (unsigned long)tcc_get_symbol_err(s1, start_symbol); if (s1->output_type == TCC_OUTPUT_MEMORY && addr) /* for -run GUI's, put '_runwinmain' instead of 'main' */ add_elf_sym(symtab_section, addr, 0, ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, text_section->sh_num, "main"); } if (pe) { pe->type = pe_type; pe->start_addr = addr; } }
uint32_t SymbolTable::addSymbol(uint32_t name, uint64_t value, uint64_t size, uint8_t bind, uint8_t type, uint32_t other, uint16_t shndx){ if (elfFile->is64Bit()){ Symbol64* sym = new Symbol64(this, NULL, symbols.size()); Elf64_Sym symEntry; symEntry.st_name = name; symEntry.st_value = value; symEntry.st_size = size; symEntry.st_info = ELF64_ST_INFO(bind,type); symEntry.st_other = other; symEntry.st_shndx = shndx; memcpy(sym->charStream(), &symEntry, Size__64_bit_Symbol); symbols.append(sym); sizeInBytes += Size__64_bit_Symbol; } else { Symbol32* sym = new Symbol32(this, NULL, symbols.size()); Elf32_Sym symEntry; symEntry.st_name = name; symEntry.st_value = (uint32_t)value; symEntry.st_size = (uint32_t)size; symEntry.st_info = ELF32_ST_INFO(bind,type); symEntry.st_other = other; symEntry.st_shndx = shndx; memcpy(sym->charStream(), &symEntry, Size__32_bit_Symbol); symbols.append(sym); sizeInBytes += Size__32_bit_Symbol; } // sortSymbols(); verify(); return symbols.size()-1; }
static void newSym32(char *name,elfull value,elfull size,uint8_t bind, uint8_t type,unsigned shndx) { struct Symbol32Node *elfsym = addSymbol32(name); setval(be,elfsym->s.st_value,4,value); setval(be,elfsym->s.st_size,4,size); elfsym->s.st_info[0] = ELF32_ST_INFO(bind,type); setval(be,elfsym->s.st_shndx,2,shndx); }
void prepare_symentry(Sym *symentry) { symentry->st_name = 1; symentry->st_value = 0; symentry->st_size = fs.st_size; #ifdef BIT32 symentry->st_info = ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT); #else symentry->st_info = ELF64_ST_INFO(STB_GLOBAL, STT_OBJECT); #endif symentry->st_other = STV_DEFAULT; symentry->st_shndx = IDX_DATA; }
/* ------------------------------------------------------------- */ PUB_FN int pe_load_def_file(TCCState *s1, int fd) { DLLReference *dllref; int state = 0, ret = -1; char line[400], dllname[80], *p; FILE *fp = fdopen(dup(fd), "rb"); if (NULL == fp) goto quit; for (;;) { p = get_line(line, sizeof line, fp); if (NULL == p) break; if (0 == *p || ';' == *p) continue; switch (state) { case 0: if (0 != strnicmp(p, "LIBRARY", 7)) goto quit; strcpy(dllname, trimfront(p+7)); ++state; continue; case 1: if (0 != stricmp(p, "EXPORTS")) goto quit; ++state; continue; case 2: dllref = tcc_malloc(sizeof(DLLReference) + strlen(dllname)); strcpy(dllref->name, dllname); dllref->level = 0; dynarray_add((void ***) &s1->loaded_dlls, &s1->nb_loaded_dlls, dllref); ++state; default: add_elf_sym(s1->dynsymtab_section, s1->nb_loaded_dlls, 0, ELF32_ST_INFO(STB_GLOBAL, STT_FUNC), 0, text_section->sh_num, p); continue; } } ret = 0; quit: if (fp) fclose(fp); if (ret) error_noabort("unrecognized export definition file format"); return ret; }
int pe_load_def_file(TCCState *s1, int fd) { DLLReference *dllref; int state = 0, ret = -1, hint; char line[400], dllname[80], *p, *ordinal; FILE *fp = fdopen(dup(fd), "rb"); if (fp == NULL) goto quit; for (;;) { p = get_line(line, sizeof line, fp); if (p == NULL) break; if (*p == 0 || *p == ';') continue; switch (state) { case 0: if (strncasecmp(p, "LIBRARY", 7) != 0) goto quit; strcpy(dllname, trimfront(p + 7)); ++state; continue; case 1: if (strcasecmp(p, "EXPORTS") != 0) goto quit; ++state; continue; case 2: dllref = tcc_malloc(sizeof(DLLReference) + strlen(dllname)); strcpy(dllref->name, dllname); dllref->level = 0; dynarray_add((void ***) &s1->loaded_dlls, &s1->nb_loaded_dlls, dllref); ++state; default: hint = 0; ordinal = strchr(p, '@'); if (ordinal) { *ordinal = 0; trimback(p, ordinal); ordinal++; hint = atoi(ordinal); } add_elf_sym(s1->dynsymtab_section, s1->nb_loaded_dlls, 0, ELF32_ST_INFO(STB_GLOBAL, STT_FUNC), hint, text_section->sh_num, p); continue; } } ret = 0; quit: if (fp) fclose(fp); if (ret) error_noabort("unrecognized export definition file format"); return ret; }
/** This function sets the Elf Symbol fields @internalComponent @released @param aSym The Symbol representation @param aElfSym The Elf Symbol @param aCodeIndex The index at which this Symbol refers to in the code section where, we have the ordinal number */ void ElfProducer::SetSymolFields(Symbol *aSym, Elf32_Sym* aElfSym, PLUINT32 aCodeIndex) { aElfSym->st_other = STV_DEFAULT; aElfSym->st_info = (PLUCHAR) (ELF32_ST_INFO(STB_GLOBAL, aSym->CodeDataType())); aElfSym->st_value = (aCodeIndex - 1)*sizeof(Elf32_Word); if(aSym->CodeDataType() == SymbolTypeCode){ aElfSym->st_size = sizeof(Elf32_Word); }else{ aElfSym->st_size = aSym->SymbolSize(); } aElfSym->st_shndx = CODE_SECTION; }
/* changesymbols() finds all symbols in a given symbol table that * appear in the namelist with the specified binding and alters their * binding strength. */ static int changesymbols(Elf32_Sym *symtab, char const *strtab, int count) { Elf32_Sym *sym; char const *name; int touched; int i; touched = FALSE; for (i = 0, sym = symtab ; i < count ; ++i, ++sym) { if (ELF32_ST_BIND(sym->st_info) != fromstrength) continue; name = strtab + sym->st_name; if (!bsearch(&name, namelist, namecount, sizeof *namelist, qstrcmp)) continue; sym->st_info = ELF32_ST_INFO(tostrength, ELF32_ST_TYPE(sym->st_info)); printf("%s \"%s\".\n", tostrengthtext, name); touched = TRUE; } return touched; }
static void elf_x86_x86_write_symtab_entry(unsigned char *bufp, elf_symtab_entry *entry, yasm_intnum *value_intn, yasm_intnum *size_intn) { YASM_WRITE_32_L(bufp, entry->name ? entry->name->index : 0); YASM_WRITE_32I_L(bufp, value_intn); YASM_WRITE_32I_L(bufp, size_intn); YASM_WRITE_8(bufp, ELF32_ST_INFO(entry->bind, entry->type)); YASM_WRITE_8(bufp, ELF32_ST_OTHER(entry->vis)); if (entry->sect) { elf_secthead *shead = yasm_section_get_data(entry->sect, &elf_section_data); if (!shead) yasm_internal_error(N_("symbol references section without data")); YASM_WRITE_16_L(bufp, shead->index); } else { YASM_WRITE_16_L(bufp, entry->index); } }
static void pe_add_runtime_ex(TCCState *s1, struct pe_info *pe) { const char *start_symbol; unsigned long addr = 0; int pe_type = 0; int start_sym_index; if (find_elf_sym(symtab_section, "_WinMain@16")) { pe_type = PE_GUI; } else if (s1->output_type == TCC_OUTPUT_DLL) { pe_type = PE_DLL; // Need this for 'tccelf.c:relocate_section()' s1->output_type = TCC_OUTPUT_EXE; } else { pe_type = PE_EXE; } start_symbol = s1->start_symbol; if (!start_symbol) { start_symbol = pe_type == PE_DLL ? "_DllMain@12" : "mainCRTStartup"; } start_sym_index = add_elf_sym(symtab_section, 0, 0, ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, SHN_UNDEF, start_symbol); tcc_get_symbol_err(s1, start_symbol); if (s1->nostdlib == 0) { tcc_add_library(s1, "c"); tcc_add_library(s1, "os"); } if (pe) { pe->type = pe_type; pe->start_sym_index = start_sym_index; pe->stub = s1->stub; pe->def = s1->def_file; pe->filealign = s1->filealign; } }
/* * Search for a symbol by name and return the corresponding symbol * information. If we're compiled _LP64, we just call Plookup_by_name * and return because ps_sym_t is defined to be an Elf64_Sym, which * is the same as a GElf_Sym. In the _ILP32 case, we have to convert * Plookup_by_name's result back to a ps_sym_t (which is an Elf32_Sym). */ ps_err_e ps_pglobal_sym(struct ps_prochandle *P, const char *object_name, const char *sym_name, ps_sym_t *symp) { #if defined(_ILP32) GElf_Sym sym; if (Plookup_by_name(P, object_name, sym_name, &sym) == 0) { symp->st_name = (Elf32_Word)sym.st_name; symp->st_value = (Elf32_Addr)sym.st_value; symp->st_size = (Elf32_Word)sym.st_size; symp->st_info = ELF32_ST_INFO( GELF_ST_BIND(sym.st_info), GELF_ST_TYPE(sym.st_info)); symp->st_other = sym.st_other; symp->st_shndx = sym.st_shndx; return (PS_OK); } #elif defined(_LP64) if (Plookup_by_name(P, object_name, sym_name, symp) == 0) return (PS_OK); #endif return (PS_NOSYM); }
// (forces align and bss_end symbol defined) }; object *root_obj = NULL; global *root_global = NULL; // global symbols section *text_sections = NULL, *data_sections = NULL; Elf32_Off text_offset = 0, // virtual sections offsets (that is, in memory) data_offset = 0; Elf32_Off data_file_offset = 0; // physical offset of data section (in file) comp_desc comp; // a component meta-data Elf32_Sym text_end_sym = { 0, 0, 0, ELF32_ST_INFO(STB_GLOBAL,STT_NOTYPE), 0, SHN_ABS }, data_end_sym = { 0, 0, 0, ELF32_ST_INFO(STB_GLOBAL,STT_NOTYPE), 0, SHN_ABS }, bss_end_sym = { 0, 0, 0, ELF32_ST_INFO(STB_GLOBAL,STT_NOTYPE), 0, SHN_ABS }, img_end_sym = { 0, 0, 0, ELF32_ST_INFO(STB_GLOBAL,STT_NOTYPE), 0, SHN_ABS }; //------------------------------------------------------------------------ // Uninitialized Data //------------------------------------------------------------------------ mt mtbl; // MUST be adjacent with the next array char trash_space[ 20000 ]; // this space gets trashed by the method table //------------------------------------------------------------------------ // Main Function
static int pe_check_symbols(struct pe_info *pe) { Elf32_Sym *sym; int sym_index, sym_end; int ret = 0; pe_align_section(text_section, 8); sym_end = symtab_section->data_offset / sizeof(Elf32_Sym); for (sym_index = 1; sym_index < sym_end; ++sym_index) { sym = (Elf32_Sym *) symtab_section->data + sym_index; if (sym->st_shndx == SHN_UNDEF) { const char *name = symtab_section->link->data + sym->st_name; unsigned type = ELF32_ST_TYPE(sym->st_info); int imp_sym = pe_find_import(pe->s1, name); struct import_symbol *is; if (imp_sym == 0) goto not_found; is = pe_add_import(pe, imp_sym); if (!is) goto not_found; if (type == STT_FUNC) { unsigned long offset = is->thk_offset; if (offset) { // Got aliased symbol, like stricmp and _stricmp } else { char buffer[100]; offset = text_section->data_offset; // Add the 'jmp IAT[x]' instruction *(WORD *) section_ptr_add(text_section, 8) = 0x25FF; // Add a helper symbol, will be patched later in pe_build_imports sprintf(buffer, "IAT.%s", name); is->iat_index = put_elf_sym(symtab_section, 0, sizeof(DWORD), ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT), 0, SHN_UNDEF, buffer); put_elf_reloc(symtab_section, text_section, offset + 2, R_386_32, is->iat_index); is->thk_offset = offset; } // tcc_realloc might have altered sym's address sym = (Elf32_Sym *) symtab_section->data + sym_index; // Patch the original symbol sym->st_value = offset; sym->st_shndx = text_section->sh_num; sym->st_other &= ~1; // Do not export continue; } if (type == STT_OBJECT) { if (is->iat_index == 0) { // Original symbol will be patched later in pe_build_imports is->iat_index = sym_index; continue; } } not_found: error_noabort("undefined symbol '%s'", name); ret = 1; } else if (pe->s1->rdynamic && ELF32_ST_BIND(sym->st_info) != STB_LOCAL) { // If -rdynamic option, then export all non local symbols sym->st_other |= 1; } } return ret; }
int main(int argc, char **argv) { ELF_SPEC_HEADER *curr = NULL, *progh = NULL , *new_dynsym = NULL, *new_dynstr = NULL,*newhash=NULL; int new_symbol_index=-1; int i=0;/* A Counter */ char *contents; new_symbol_name=(char *)malloc(sizeof("new_symbol_avijit")); char *tmp="new_symbol_avijit"; for(i=0;i<sizeof("new_symbol_avijit");i++) new_symbol_name[i]=*(tmp+i); new_symbol_name[sizeof("new_symbol_avijit")-1]='\0'; new_symbol_size=sizeof("new_symbol_avijit"); char *dynsym_data,*dynstr_data; int *hash_data; int first_load_segment = 1; unsigned long hash_bucket=elf_hash(new_symbol_name); Elf32_Addr dynamic_section_addr=0; ELF_SPEC_HEADER *dynamic_segment = NULL; if (argc != 4){ fprintf(stderr, "Usage: %s <input-file> <output-file> <new data>\n",argv[0]); return 0; } printf("Displaying the data to be inserted: %s\n",argv[3]); if(init(argv[1])){ exit(1); } find_sections(); extra_pages=calculate_extra_pages(sizeof(*argv[3])); calculate_new_addresses(new_symbol_size); printf("Extra Pages required: %d\n",extra_pages); curr=melf_sectionAdd(melf); new_dynsym = melf_sectionAdd(melf); new_dynstr = melf_sectionAdd(melf); newhash=melf_sectionAdd(melf); newdata_size=PAGE_SIZE*extra_pages-dynsym_size-dynstr_size-hash_size; printf("new data size recalculated: 0x%x\n",newdata_size); contents=(char *)malloc(newdata_size); dynsym_data=(char *)malloc(old_dynsym_size+melf_sectionGetEntrySize(melf,old_dynsym)); dynstr_data=(char *)malloc(old_dynstr_size+new_symbol_size); hash_data=(int*)malloc(old_hash_size+4); strcpy(contents, argv[3]); /* Fixing dynsym section */ void *prev_dynsym_contents=melf_sectionGetContent(melf,old_dynsym); bcopy(prev_dynsym_contents,dynsym_data,old_dynsym_size); /* Calculating the index of the symbol to be added */ new_symbol_index=old_dynsym_size/melf_sectionGetEntrySize(melf,old_dynsym); printf(".dynsym contents:\n"); for(i=0;i<old_dynsym_size;i++) printf("%c ",dynsym_data[i]>31?dynsym_data[i]:'.'); printf("\n"); /* Add the entry for pointing to corresponding entry in the .dynstr */ char new_entry[16]; for(i=0;i<16;i++) new_entry[i]=(char)0x0; /* Calculating the index of new symbol in the dynstr */ int new_index=old_dynstr_size; /* Remember that index in dynstr is really the offset from start of section */ Elf32_Sym *elf_sym=(Elf32_Sym *)malloc(sizeof(Elf32_Sym)); elf_sym->st_name=new_index; elf_sym->st_value=newdata_addr; elf_sym->st_size=new_symbol_size; elf_sym->st_info=ELF32_ST_INFO(STB_GLOBAL,STT_OBJECT); elf_sym->st_other=ELF32_ST_OTHER(STV_DEFAULT); elf_sym->st_shndx=(Elf32_Half)melf_sectionGetIndex(melf,curr); for(i=0;i<16;i++){ dynsym_data[i+old_dynsym_size]=*(char *)((void*)elf_sym+i)/*new_entry[i]*/; printf("Emitting : 0x%d\n",new_entry[i]); } /* Change the pointer of new_dynsym to that of the old dynsym */ melf_sectionSetContent(melf,new_dynsym,prev_dynsym_contents,old_dynsym_size); melf_sectionSetType(melf,new_dynsym,SHT_PROGBITS); melf_sectionSetAddress(melf,new_dynsym,old_dynsym->spec.section.sh_addr); melf_sectionSetFlags(melf, new_dynsym, SHF_ALLOC); /* Set the dynsym section properly */ melf_sectionSetAddress(melf,old_dynsym,dynsym_addr); melf_sectionSetContent(melf,old_dynsym,dynsym_data,old_dynsym_size+melf_sectionGetEntrySize(melf,old_dynsym)); /* Fixing dynstr */ void *prev_dynstr_contents=melf_sectionGetContent(melf,old_dynstr); bcopy(prev_dynstr_contents,dynstr_data,old_dynstr_size); for(i=0;i<new_symbol_size;i++) dynstr_data[old_dynstr_size+i]=new_symbol_name[i]; printf(".dynstr contents:\n"); printf("New symbol size= %d\n",new_symbol_size); for(i=0;i<old_dynstr_size+new_symbol_size;i++) printf("%c ",dynstr_data[i]>31?dynstr_data[i]:'.'); printf("\n"); printf("Contents copied dynstr: %s\n",dynstr_data); melf_sectionSetContent(melf,new_dynstr,prev_dynstr_contents,old_dynstr_size); melf_sectionSetType(melf,new_dynstr,SHT_PROGBITS); melf_sectionSetAddress(melf,new_dynstr,old_dynstr->spec.section.sh_addr); melf_sectionSetFlags(melf, new_dynstr, SHF_ALLOC); melf_sectionSetAddress(melf,old_dynstr,dynstr_addr); melf_sectionSetContent(melf,old_dynstr,dynstr_data,old_dynstr_size+new_symbol_size); /* Done Fixing dynsym and dynstr */ /* Fix hash section */ void *prev_hash_contents=melf_sectionGetContent(melf,old_hash); hash_data=malloc(old_hash_size+4); bcopy(prev_hash_contents,hash_data,old_hash_size); melf_sectionSetContent(melf,newhash,prev_hash_contents,old_hash_size); melf_sectionSetType(melf,newhash,SHT_PROGBITS/*melf_sectionGetType(melf,old_hash)*/); melf_sectionSetAddress(melf,newhash,old_hash->spec.section.sh_addr); melf_sectionSetFlags(melf, newhash,SHF_ALLOC/*melf_sectionGetFlags(melf,old_hash)*/); /* Calculate hash value of new symbol and insert it in the chain properly */ printf("Printing out the original contents of .hash\n"); for(i=0;i<old_hash->spec.section.sh_size/4;i++) printf("%d\n",(int)*(hash_data+i)); add_new_chain(hash_bucket,hash_data,new_symbol_index); printf("Hash bucket is: %ld\n",hash_bucket%nbuckets); printf("Printing out the new hash table\n"); for(i=0;i<sizeof(hash_data);i++) printf("0x%x\n",hash_data[i]&0xff); /* Set the hash table properly */ melf_sectionSetAddress(melf,old_hash,hash_addr); melf_sectionSetContent(melf,old_hash,hash_data,old_hash_size+4); /* Done Fixing hash section */ if (!curr) { fprintf(stderr, "Cannot create new section\n"); return 1; } melf_sectionSetType(melf, curr, SHT_PROGBITS); melf_sectionSetFlags(melf, curr, SHF_ALLOC); melf_sectionSetAddress(melf, curr, newdata_addr); melf_sectionSetContent(melf, curr, contents,newdata_size); // change the segment map progh = melf_programGetEnum(melf); while (progh) { switch (melf_programGetType(melf, progh)) { case PT_PHDR: melf_programSetVirtualAddress(melf, progh, melf_programGetVirtualAddress(melf, progh) - PAGE_SIZE*extra_pages); melf_programSetPhysicalAddress(melf, progh, melf_programGetPhysicalAddress(melf, progh) - PAGE_SIZE*extra_pages); break; case PT_LOAD: if (first_load_segment) { melf_programSetVirtualAddress(melf, progh, melf_programGetVirtualAddress(melf, progh) - PAGE_SIZE*extra_pages); melf_programSetPhysicalAddress(melf, progh, melf_programGetPhysicalAddress(melf, progh) - PAGE_SIZE*extra_pages); melf_programSetPhysicalSize(melf, progh, melf_programGetPhysicalSize(melf, progh) + PAGE_SIZE*extra_pages); melf_programSetVirtualSize(melf, progh, melf_programGetVirtualSize(melf, progh) + PAGE_SIZE*extra_pages); first_load_segment = 0; } else progh->spec.program.p_offset += PAGE_SIZE*extra_pages; break; case PT_DYNAMIC: dynamic_section_addr=progh->spec.section.sh_addr; dynamic_segment=progh; case PT_INTERP: default: progh->spec.program.p_offset += PAGE_SIZE*extra_pages; break; } progh = melf_programEnumNext(melf, progh); } if(!melf_dynamicSetTag(melf,old_dynamic,DT_SYMTAB,dynsym_addr)|| !melf_dynamicSetTag(melf,old_dynamic,DT_STRTAB,dynstr_addr)|| !melf_dynamicSetTag(melf,old_dynamic,DT_HASH,hash_addr)){ fprintf(stderr,"Error in reassigning pointers iin .dynamic\n"); return 1; } melf_save(melf, argv[2]); melf_destroy(melf); return 0; }
Elf_Scn *symtab_write_elf(Elf *e, struct sect * sects, struct buffer *strtab_buf, struct buffer *shstrtab_buf) { unsigned i, k; struct sym_info *sym; Elf32_Sym esym; Elf_Scn *scn, *relscn, *tmpscn; Elf_Data *data, *reldata; Elf32_Shdr *shdr, *relshdr; struct buffer buf; struct buffer *relbuf; struct sect *s; buffer_init(&buf); esym.st_name = 0; esym.st_value = 0; esym.st_size = 0; esym.st_info = 0; esym.st_other = 0; esym.st_shndx = 0; buffer_writemem(&buf, &esym, sizeof(esym)); relbuf = malloc(0); for (s = sects, k = 0; s != NULL; s = s->next, k++) { relbuf = realloc(relbuf, (k+1)*sizeof(struct buffer)); buffer_init(&relbuf[k]); } for (i = 0; i < SYMTAB_SIZE; i++) { for (sym = symtab[i]; sym != NULL; sym = sym->next) { if (sym->symbol[0] != '.' || sym->relocs != NULL) { struct reloc_info size; int type = STT_NOTYPE; int bind = STB_LOCAL; if (!sym->defined || sym->bind == SYM_BIND_GLOBAL) { bind = STB_GLOBAL; } esym.st_name = strtab_buf->pos; buffer_writestr(strtab_buf, sym->symbol); esym.st_value = sym->addr; size = expr_evaluate(sym->size); if (size.symbol != NULL) { eprintf("Cannot relocate symbol size"); exit(EXIT_FAILURE); } esym.st_size = size.intval; if (strcmp(sym->type, "@function") == 0) type = STT_FUNC; if (strcmp(sym->type, "@object") == 0) type = STT_OBJECT; esym.st_info = ELF32_ST_INFO(bind, type); esym.st_other = ELF32_ST_VISIBILITY(STV_DEFAULT); tmpscn = section_find(e, sym->section, shstrtab_buf); if (tmpscn == NULL && sym->section != NULL) tmpscn = section_find(e, pile_name(pile_match(sym->section)), shstrtab_buf); esym.st_shndx = tmpscn != NULL ? elf_ndxscn(tmpscn) : 0; if (sym->relocs != NULL) { struct sym_reloc_info *r; for (r = sym->relocs; r != NULL; r = r->next) { Elf32_Rela rel; rel.r_offset = r->addr; rel.r_info = ELF32_R_INFO(buf.pos/sizeof(esym), r->type); rel.r_addend = r->addend; for (s = sects, k = 0; s != NULL; s = s->next, k++) { if (strcmp(s->name, r->sect) == 0) { buffer_writemem(&relbuf[k], &rel, sizeof(rel)); } } } } buffer_writemem(&buf, &esym, sizeof(esym)); } } } scn = xelf_newscn(e); shdr = xelf32_getshdr(scn); shdr->sh_name = shstrtab_buf->pos; buffer_writestr(shstrtab_buf, ".symtab"); shdr->sh_type = SHT_SYMTAB; shdr->sh_flags = 0; data = xelf_newdata(scn); data->d_align = 4; data->d_off = 0; data->d_type = ELF_T_SYM; data->d_version = EV_CURRENT; data->d_buf = buf.data; data->d_size = buf.pos; for (s = sects, k = 0; s != NULL; s = s->next, k++) { if (relbuf[k].pos > 0) { char *relname; relscn = xelf_newscn(e); relshdr = xelf32_getshdr(relscn); relshdr->sh_name = shstrtab_buf->pos; relname = malloc(strlen(s->name)+6); strcpy(relname, ".rela"); strcat(relname, s->name); buffer_writestr(shstrtab_buf, relname); relshdr->sh_type = SHT_RELA; shdr->sh_flags = 0; reldata = xelf_newdata(relscn); reldata->d_align = 4; reldata->d_off = 0; reldata->d_type = ELF_T_RELA; reldata->d_version = EV_CURRENT; reldata->d_buf = relbuf[k].data; reldata->d_size = relbuf[k].pos; relshdr->sh_link = elf_ndxscn(scn); tmpscn = section_find(e, s->name, shstrtab_buf); relshdr->sh_info = tmpscn != NULL ? elf_ndxscn(tmpscn) : 0; } } return scn; }