Skip to content

Commit

Permalink
Dwarf-EH: add -fPIC support
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterBright committed Dec 27, 2015
1 parent d5c6f04 commit 58910e7
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 10 deletions.
2 changes: 2 additions & 0 deletions src/backend/cc.h
Expand Up @@ -1273,6 +1273,8 @@ struct Symbol
int Sweight; // usage count, the higher the number,
// the more worthwhile it is to put in
// a register
int Sdw_ref_idx; // !=0 means index of DW.ref.name symbol (Dwarf EH)

union
{
unsigned Sxtrnnum_; // SCcomdef,SCextern,SCcomdat: external symbol # (starting from 1)
Expand Down
1 change: 1 addition & 0 deletions src/backend/cod3.c
Expand Up @@ -551,6 +551,7 @@ regm_t regmask(tym_t tym, tym_t tyf)
{
case TYvoid:
case TYstruct:
case TYarray:
return 0;
case TYbool:
case TYwchar_t:
Expand Down
30 changes: 26 additions & 4 deletions src/backend/dwarf.c
Expand Up @@ -60,6 +60,12 @@

extern int seg_count;

#if ELFOBJ
IDXSYM elf_addsym(IDXSTR nam, targ_size_t val, unsigned sz,
unsigned typ, unsigned bind, IDXSEC sec,
unsigned char visibility = STV_DEFAULT);
#endif

static char __file__[] = __FILE__; // for tassert.h
#include "tassert.h"

Expand Down Expand Up @@ -626,10 +632,16 @@ static void writeEhFrameHeader(IDXSEC dfseg, Outbuffer *buf, Symbol *personality
buf->writeByten(I64 ? 16 : 8); // return address register
if (config.ehmethod == EH_DWARF)
{
const unsigned char personality_pointer_encoding = config.flags3 & CFG3pic
? DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4
: DW_EH_PE_absptr | DW_EH_PE_udata4;
const unsigned char LSDA_pointer_encoding = config.flags3 & CFG3pic
? DW_EH_PE_pcrel | DW_EH_PE_sdata4
: DW_EH_PE_absptr | DW_EH_PE_udata4;
buf->writeByten(7); // Augmentation Length
buf->writeByten(DW_EH_PE_absptr | DW_EH_PE_udata4); // P: personality routing address encoding
ElfObj::reftoident(dfseg, buf->size(), personality, 0, CFoff); // PC_begin
buf->writeByten(DW_EH_PE_absptr | DW_EH_PE_udata4); // L: address encoding for LSDA in FDE
buf->writeByten(personality_pointer_encoding); // P: personality routine address encoding
dwarf_reftoident(dfseg, buf->size(), personality, 0);
buf->writeByten(LSDA_pointer_encoding); // L: address encoding for LSDA in FDE
buf->writeByten(DW_EH_PE_pcrel | DW_EH_PE_sdata4); // R: encoding of addresses in FDE
}
else
Expand Down Expand Up @@ -785,8 +797,18 @@ void writeEhFrameFDE(IDXSEC dfseg, Symbol *sfunc)
{
buf->writeByten(4); // Augmentation Data Length
int etseg = dwarf_getsegment_alloc(except_table_name, 1);
// if CFG3pic, fixup should be R_X86_64_PC32
buf->write32(0); // address of LSDA (".gcc_except_table")
dwarf_addrel(dfseg, buf->size() - 4, etseg, sfunc->Sfunc->LSDAoffset); // and the fixup
if (config.flags3 & CFG3pic)
{
#if ELFOBJ
ElfObj::addrel(dfseg, buf->size() - 4, R_X86_64_PC32, MAP_SEG2SYMIDX(etseg), sfunc->Sfunc->LSDAoffset);
#else
assert(0); // not supported yet
#endif
}
else
dwarf_addrel(dfseg, buf->size() - 4, etseg, sfunc->Sfunc->LSDAoffset); // and the fixup
}
else
buf->writeByten(0); // Augmentation Data Length
Expand Down
1 change: 1 addition & 0 deletions src/backend/dwarf.h
Expand Up @@ -18,6 +18,7 @@ unsigned dwarf_abbrev_code(unsigned char *data, size_t nbytes);
int dwarf_regno(int reg);

void dwarf_addrel(int seg, targ_size_t offset, int targseg, targ_size_t val = 0);
int dwarf_reftoident(int seg, targ_size_t offset, Symbol *s, targ_size_t val);
void dwarf_except_gentables(Funcsym *sfunc, unsigned startoffset, unsigned retoffset);
void genDwarfEh(Funcsym *sfunc, int seg, Outbuffer *et, bool scancode, unsigned startoffset, unsigned retoffset);

Expand Down
7 changes: 4 additions & 3 deletions src/backend/dwarfeh.c
Expand Up @@ -293,7 +293,9 @@ void genDwarfEh(Funcsym *sfunc, int seg, Outbuffer *et, bool scancode, unsigned
if (LPstart != DW_EH_PE_omit)
et->writeuLEB128(LPbase);

const unsigned char TType = DW_EH_PE_absptr | DW_EH_PE_udata4;
const unsigned char TType = (config.flags3 & CFG3pic)
? DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4
: DW_EH_PE_absptr | DW_EH_PE_udata4;
et->writeByte(TType);

/* Compute TTbase, which is the sum of:
Expand Down Expand Up @@ -345,8 +347,7 @@ void genDwarfEh(Funcsym *sfunc, int seg, Outbuffer *et, bool scancode, unsigned
for (int i = sfunc->Sfunc->typesTableDim; i--; )
{
Symbol *s = typesTable[i];
ElfObj::reftoident(seg, et->size(), s, 0, CFoff); //dwarf_addrel(seg, et->size(), s->Sseg, s->Soffset);
//et->write32(s->Soffset);
dwarf_reftoident(seg, et->size(), s, 0);
}
assert(TToffset == et->size() - startsize);
}
Expand Down
50 changes: 50 additions & 0 deletions src/backend/elfobj.c
Expand Up @@ -3496,4 +3496,54 @@ void Obj::gotref(symbol *s)
}

#endif

/******************************************
* Generate fixup specific to .eh_frame and .gcc_except_table sections.
* Params:
* seg = segment of where to write fixup
* offset = offset of where to write fixup
* s = fixup is a reference to this Symbol
* val = displacement from s
* Returns:
* number of bytes written at seg:offset
*/
int dwarf_reftoident(int seg, targ_size_t offset, Symbol *s, targ_size_t val)
{
assert(I64); // I32 not implemented yet

if (config.flags3 & CFG3pic)
{
/* fixup: R_X86_64_PC32 sym="DW.ref.name"
* symtab: .weak DW.ref.name,@OBJECT,VALUE=.data.DW.ref.name+0x00,SIZE=8
* Section 13 .data.DW.ref.name PROGBITS,ALLOC,WRITE,SIZE=0x0008(8),OFFSET=0x0138,ALIGN=8
* 0138: 0 0 0 0 0 0 0 0 ........
* Section 14 .rela.data.DW.ref.name RELA,ENTRIES=1,OFFSET=0x0E18,ALIGN=8,LINK=22,INFO=13
* 0 offset=00000000 addend=0000000000000000 type=R_X86_64_64 sym="name"
*/
if (!s->Sdw_ref_idx)
{
int dataDWref_seg = ElfObj::getsegment(".data.DW.ref.", s->Sident, SHT_PROGBITS, SHF_ALLOC|SHF_WRITE, 8);
Outbuffer *buf = SegData[dataDWref_seg]->SDbuf;
assert(buf->size() == 0);
ElfObj::reftoident(dataDWref_seg, 0, s, 0, CFoffset64);

// Add "DW.ref." ~ name to the symtab_strings table
IDXSTR namidx = symtab_strings->size();
symtab_strings->writeString("DW.ref.");
symtab_strings->setsize(symtab_strings->size() - 1); // back up over terminating 0
symtab_strings->writeString(s->Sident);

s->Sdw_ref_idx = elf_addsym(namidx, val, 8, STT_OBJECT, STB_WEAK, MAP_SEG2SECIDX(dataDWref_seg), STV_HIDDEN);
}
ElfObj::writerel(seg, offset, R_X86_64_PC32, s->Sdw_ref_idx, 0);
}
else
{
ElfObj::reftoident(seg, offset, s, val, CFoff);
//dwarf_addrel(seg, offset, s->Sseg, s->Soffset);
//et->write32(s->Soffset);
}
return 4;
}

#endif
19 changes: 16 additions & 3 deletions src/backend/machobj.c
Expand Up @@ -2309,9 +2309,6 @@ void MachObj::addrel(int seg, targ_size_t offset, symbol *targsym,
unsigned targseg, int rtype, int val)
{
Relocation rel;
#ifdef DEBUG
memset(&rel, 0, sizeof(rel));
#endif
rel.offset = offset;
rel.targsym = targsym;
rel.targseg = targseg;
Expand Down Expand Up @@ -2704,5 +2701,21 @@ void Obj::gotref(symbol *s)
}
}

/******************************************
* Generate fixup specific to .eh_frame and .gcc_except_table sections.
* Params:
* seg = segment of where to write fixup
* offset = offset of where to write fixup
* s = fixup is a reference to this Symbol
* val = displacement from s
* Returns:
* number of bytes written at seg:offset
*/
int dwarf_reftoident(int seg, targ_size_t offset, Symbol *s, targ_size_t val)
{
assert(0); // not implemented yet
return 4;
}

#endif
#endif

0 comments on commit 58910e7

Please sign in to comment.