From 85f6062e050c8139582dac0e65bfda71e90f8ab7 Mon Sep 17 00:00:00 2001 From: sergei Date: Wed, 13 Jun 2012 16:40:50 +0000 Subject: [PATCH] * Reworked writing ELF symbols into a separate class, TElfSymtab, which is also suitable for creating symbol tables in executable and dynamic ELF files. * Do not write ELF symbols for internal sections (symbol/string table, relocation sections and alike). git-svn-id: trunk@21592 - --- compiler/ogelf.pas | 229 +++++++++++++++++++++++++-------------------- 1 file changed, 129 insertions(+), 100 deletions(-) diff --git a/compiler/ogelf.pas b/compiler/ogelf.pas index 4f8d10f429..e31b3a89d3 100644 --- a/compiler/ogelf.pas +++ b/compiler/ogelf.pas @@ -50,6 +50,18 @@ interface constructor create_ext(aobjdata:TObjData;const Aname:string;Ashtype,Ashflags,Ashlink,Ashinfo:longint;Aalign:shortint;Aentsize:longint); end; + TElfSymtabKind = (esk_obj,esk_exe,esk_dyn); + + TElfSymtab = class(TElfObjSection) + public + kind: TElfSymtabKind; + fstrsec: TObjSection; + symidx: longint; + constructor create(aObjData:TObjData;aKind:TElfSymtabKind);reintroduce; + procedure writeSymbol(objsym:TObjSymbol); + procedure writeInternalSymbol(astridx:longint;ainfo:byte;ashndx:word); + end; + TElfObjData = class(TObjData) public constructor create(const n:string);override; @@ -60,21 +72,12 @@ interface TElfObjectOutput = class(tObjOutput) private - symtabsect, - strtabsect, + symtabsect: TElfSymtab; shstrtabsect: TElfObjSection; - {gotpcsect, - gotoffsect, - goTSect, - plTSect, - symsect : TElfObjSection;} - symidx, - localsyms : longint; procedure createrelocsection(s:TElfObjSection;data:TObjData); procedure createshstrtab(data:TObjData); procedure createsymtab(data: TObjData); procedure writesectionheader(s:TElfObjSection); - procedure write_internal_symbol(astridx:longint;ainfo:byte;ashndx:word); procedure section_write_symbol(p:TObject;arg:pointer); procedure section_write_sh_string(p:TObject;arg:pointer); procedure section_count_sections(p:TObject;arg:pointer); @@ -928,6 +931,108 @@ implementation end; +{**************************************************************************** + TElfSymtab +****************************************************************************} + + const + symsecnames: array[boolean] of string[8] = ('.symtab','.dynsym'); + strsecnames: array[boolean] of string[8] = ('.strtab','.dynstr'); + symsectypes: array[boolean] of longint = (SHT_SYMTAB,SHT_DYNSYM); + symsecattrs: array[boolean] of longint = (0,SHF_ALLOC); + + + constructor TElfSymtab.create(aObjData:TObjData;aKind:TElfSymtabKind); + var + dyn:boolean; + begin + dyn:=(aKind=esk_dyn); + create_ext(aObjData,symsecnames[dyn],symsectypes[dyn],symsecattrs[dyn],0,0,sizeof(pint),sizeof(TElfSymbol)); + fstrsec:=TElfObjSection.create_ext(aObjData,strsecnames[dyn],SHT_STRTAB,symsecattrs[dyn],0,0,1,0); + fstrsec.writestr(#0); + writezeros(sizeof(TElfSymbol)); + symidx:=1; + shinfo:=1; + kind:=aKind; + end; + + procedure TElfSymtab.writeInternalSymbol(astridx:longint;ainfo:byte;ashndx:word); + var + elfsym:TElfSymbol; + begin + fillchar(elfsym,sizeof(elfsym),0); + elfsym.st_name:=astridx; + elfsym.st_info:=ainfo; + elfsym.st_shndx:=ashndx; + inc(symidx); + inc(shinfo); + MaybeSwapElfSymbol(elfsym); + write(elfsym,sizeof(elfsym)); + end; + + procedure TElfSymtab.writeSymbol(objsym:TObjSymbol); + var + elfsym:TElfSymbol; + begin + fillchar(elfsym,sizeof(elfsym),0); + { symbolname, write the #0 separate to overcome 255+1 char not possible } + elfsym.st_name:=fstrsec.writestr(objsym.name); + fstrsec.writestr(#0); + elfsym.st_size:=objsym.size; + case objsym.bind of + AB_LOCAL : + begin + elfsym.st_value:=objsym.address; + elfsym.st_info:=STB_LOCAL shl 4; + inc(shinfo); + end; + AB_COMMON : + begin + elfsym.st_value:=$10; { ?? should not be hardcoded } + elfsym.st_info:=STB_GLOBAL shl 4; + elfsym.st_shndx:=SHN_COMMON; + end; + AB_EXTERNAL : + elfsym.st_info:=STB_GLOBAL shl 4; + AB_WEAK_EXTERNAL : + elfsym.st_info:=STB_WEAK shl 4; + AB_GLOBAL : + begin + elfsym.st_value:=objsym.address; + elfsym.st_info:=STB_GLOBAL shl 4; + end; + end; + if (objsym.bind<>AB_EXTERNAL) {and + not(assigned(objsym.objsection) and + not(oso_data in objsym.objsection.secoptions))} then + begin + case objsym.typ of + AT_FUNCTION : + elfsym.st_info:=elfsym.st_info or STT_FUNC; + AT_DATA : + elfsym.st_info:=elfsym.st_info or STT_OBJECT; + end; + end; + if objsym.bind<>AB_COMMON then + begin + if kind<>esk_obj then + begin + { TODO } + end + else + begin + if assigned(objsym.objsection) then + elfsym.st_shndx:=TElfObjSection(objsym.objsection).secshidx + else + elfsym.st_shndx:=SHN_UNDEF; + objsym.symidx:=symidx; + end; + end; + inc(symidx); + MaybeSwapElfSymbol(elfsym); + write(elfsym,sizeof(TElfSymbol)); + end; + {**************************************************************************** TElfObjectOutput ****************************************************************************} @@ -1080,100 +1185,26 @@ implementation end; - procedure TElfObjectOutput.write_internal_symbol(astridx:longint;ainfo:byte;ashndx:word); - var - elfsym : telfsymbol; - begin - fillchar(elfsym,sizeof(elfsym),0); - elfsym.st_name:=astridx; - elfsym.st_info:=ainfo; - elfsym.st_shndx:=ashndx; - inc(symidx); - inc(localsyms); - MaybeSwapElfSymbol(elfsym); - symtabsect.write(elfsym,sizeof(elfsym)); - end; - - procedure TElfObjectOutput.section_write_symbol(p:TObject;arg:pointer); begin - TObjSection(p).secsymidx:=symidx; - write_internal_symbol(0,STT_SECTION,TElfObjSection(p).secshidx); + { Must not write symbols for internal sections like .symtab } + { TODO: maybe use inclusive list of section types instead } + if (TElfObjSection(p).shtype in [SHT_SYMTAB,SHT_STRTAB,SHT_REL,SHT_RELA]) then + exit; + TObjSection(p).secsymidx:=symtabsect.symidx; + symtabsect.writeInternalSymbol(0,STT_SECTION,TElfObjSection(p).secshidx); end; procedure TElfObjectOutput.createsymtab(data: TObjData); - - procedure WriteSym(objsym:TObjSymbol); - var - elfsym : telfsymbol; - begin - fillchar(elfsym,sizeof(elfsym),0); - { symbolname, write the #0 separate to overcome 255+1 char not possible } - elfsym.st_name:=strtabsect.Size; - strtabsect.writestr(objsym.name); - strtabsect.writestr(#0); - elfsym.st_size:=objsym.size; - case objsym.bind of - AB_LOCAL : - begin - elfsym.st_value:=objsym.address; - elfsym.st_info:=STB_LOCAL shl 4; - inc(localsyms); - end; - AB_COMMON : - begin - elfsym.st_value:=$10; - elfsym.st_info:=STB_GLOBAL shl 4; - end; - AB_EXTERNAL : - elfsym.st_info:=STB_GLOBAL shl 4; - AB_WEAK_EXTERNAL : - elfsym.st_info:=STB_WEAK shl 4; - AB_GLOBAL : - begin - elfsym.st_value:=objsym.address; - elfsym.st_info:=STB_GLOBAL shl 4; - end; - end; - if (objsym.bind<>AB_EXTERNAL) {and - not(assigned(objsym.objsection) and - not(oso_data in objsym.objsection.secoptions))} then - begin - case objsym.typ of - AT_FUNCTION : - elfsym.st_info:=elfsym.st_info or STT_FUNC; - AT_DATA : - elfsym.st_info:=elfsym.st_info or STT_OBJECT; - end; - end; - if objsym.bind=AB_COMMON then - elfsym.st_shndx:=SHN_COMMON - else - begin - if assigned(objsym.objsection) then - elfsym.st_shndx:=TElfObjSection(objsym.objsection).secshidx - else - elfsym.st_shndx:=SHN_UNDEF; - end; - objsym.symidx:=symidx; - inc(symidx); - MaybeSwapElfSymbol(elfsym); - symtabsect.write(elfsym,sizeof(elfsym)); - end; - var i : longint; objsym : TObjSymbol; begin with data do begin - symidx:=0; - localsyms:=0; - { empty entry } - write_internal_symbol(0,0,0); { filename entry } - write_internal_symbol(1,STT_FILE,SHN_ABS); + symtabsect.writeInternalSymbol(1,STT_FILE,SHN_ABS); { section } ObjSectionList.ForEachCall(@section_write_symbol,nil); { First the Local Symbols, this is required by ELF. The localsyms @@ -1183,18 +1214,17 @@ implementation begin objsym:=TObjSymbol(ObjSymbolList[i]); if (objsym.bind=AB_LOCAL) and (objsym.typ<>AT_LABEL) then - WriteSym(objsym); + symtabsect.WriteSymbol(objsym); end; { Global Symbols } for i:=0 to ObjSymbolList.Count-1 do begin objsym:=TObjSymbol(ObjSymbolList[i]); if (objsym.bind<>AB_LOCAL) then - WriteSym(objsym); + symtabsect.WriteSymbol(objsym); end; { update the .symtab section header } - symtabsect.shlink:=strtabsect.secshidx; - symtabsect.shinfo:=localsyms; + symtabsect.shlink:=TElfObjSection(symtabsect.fstrsec).secshidx; end; end; @@ -1265,16 +1295,15 @@ implementation with data do begin { default sections } - symtabsect:=TElfObjSection.create_ext(data,'.symtab',SHT_SYMTAB,0,0,0,4,sizeof(telfsymbol)); - strtabsect:=TElfObjSection.create_ext(data,'.strtab',SHT_STRTAB,0,0,0,1,0); + symtabsect:=TElfSymtab.create(data,esk_obj); shstrtabsect:=TElfObjSection.create_ext(data,'.shstrtab',SHT_STRTAB,0,0,0,1,0); { "no executable stack" marker for Linux } if (target_info.system in systems_linux) and not(cs_executable_stack in current_settings.moduleswitches) then TElfObjSection.create_ext(data,'.note.GNU-stack',SHT_PROGBITS,0,0,0,1,0); - { insert the empty and filename as first in strtab } - strtabsect.writestr(#0); - strtabsect.writestr(ExtractFileName(current_module.mainsource)+#0); + { insert filename as first in strtab } + symtabsect.fstrsec.writestr(ExtractFileName(current_module.mainsource)); + symtabsect.fstrsec.writestr(#0); { calc amount of sections we have } nsections:=1; { also create the index in the section header table }