* 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 -
This commit is contained in:
sergei 2012-06-13 16:40:50 +00:00
parent f2ccc9f593
commit 85f6062e05

View File

@ -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 }