Skip to content

Commit

Permalink
Merge pull request #3187 from MartinNowak/fix11171
Browse files Browse the repository at this point in the history
[dll] fix Issue 11171 – Text relocations in Phobos shared library
  • Loading branch information
WalterBright committed Feb 10, 2014
2 parents 6503da6 + 249844e commit 7065361
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 22 deletions.
1 change: 1 addition & 0 deletions src/backend/cdef.h
Expand Up @@ -575,6 +575,7 @@ typedef targ_uns targ_size_t; /* size_t for the target machine */
#define DATA 2 /* initialized data */
#define CDATA 3 /* constant data */
#define UDATA 4 /* uninitialized data */
#define CDATAREL 5 /* constant data with relocs */
#define UNKNOWN -1 /* unknown segment */
#define DGROUPIDX 1 /* group index of DGROUP */

Expand Down
19 changes: 19 additions & 0 deletions src/backend/dt.c
Expand Up @@ -390,6 +390,25 @@ bool dtallzeros(const dt_t *dt)
return dt->dt == DT_azeros && !dt->DTnext;
}

/************************************
* Return true if dt contains pointers (requires relocations).
*/

bool dtpointers(const dt_t *dtstart)
{
for (const dt_t *dt = dtstart; dt; dt = dt->DTnext)
{
switch (dt->dt)
{
case DT_abytes:
case DT_xoff:
case DT_coff:
return true;
}
}
return false;
}

/***********************************
* Turn DT_azeros into DTcommon
*/
Expand Down
1 change: 1 addition & 0 deletions src/backend/dt.h
Expand Up @@ -27,6 +27,7 @@ void init_common(Symbol *);
unsigned dt_size(const dt_t *dtstart);
dt_t **dtend(dt_t** pdt);
bool dtallzeros(const dt_t *dt);
bool dtpointers(const dt_t *dt);
void dt2common(dt_t **pdt);

#endif /* DT_H */
Expand Down
60 changes: 39 additions & 21 deletions src/backend/elfobj.c
Expand Up @@ -227,6 +227,8 @@ static int section_cnt; // Number of sections in table
#define SHN_SECNAMES 9
#define SHN_COM 10
#define SHN_NOTE 11
#define SHN_GNUSTACK 12
#define SHN_CDATAREL 13

IDXSYM *mapsec2sym;
#define S2S_INC 20
Expand All @@ -244,6 +246,7 @@ static int local_cnt; // Number of symbols with STB_LOCAL
#define STI_RODAT 6 // Symbol for readonly data
#define STI_NOTE 7 // Where note symbol table entry is
#define STI_COM 8
#define STI_CDATAREL 9 // Symbol for readonly data with relocations

// NOTE: There seems to be a requirement that the read-only data have the
// same symbol table index and section index. Use section NOTE as a place
Expand Down Expand Up @@ -276,7 +279,7 @@ static const char compiler[] = "\0Digital Mars C/C++"
// same section as initialized data or code, so section offsets should
// be continuous when adding data. Fix-ups anywhere withing existing data.

#define COMD UDATA+1
#define COMD CDATAREL+1
#define OB_SEG_SIZ 10 // initial number of segments supported
#define OB_SEG_INC 10 // increment for additional segments

Expand Down Expand Up @@ -696,7 +699,7 @@ Obj *Obj::init(Outbuffer *objbuf, const char *filename, const char *csegname)
if (I64)
{
static char section_names_init64[] =
"\0.symtab\0.strtab\0.shstrtab\0.text\0.data\0.bss\0.note\0.comment\0.rodata\0.note.GNU-stack\0.rela.text\0.rela.data";
"\0.symtab\0.strtab\0.shstrtab\0.text\0.data\0.bss\0.note\0.comment\0.rodata\0.note.GNU-stack\0.data.rel.ro\0.rela.text\0.rela.data";
#define NAMIDX_NONE 0
#define NAMIDX_SYMTAB 1 // .symtab
#define NAMIDX_STRTAB 9 // .strtab
Expand All @@ -708,9 +711,10 @@ Obj *Obj::init(Outbuffer *objbuf, const char *filename, const char *csegname)
#define NAMIDX_COMMENT 50 // .comment
#define NAMIDX_RODATA 59 // .rodata
#define NAMIDX_GNUSTACK 67 // .note.GNU-stack
#define NAMIDX_RELTEXT 83 // .rel.text and .rela.text
#define NAMIDX_RELDATA 93 // .rel.data
#define NAMIDX_RELDATA64 94 // .rela.data
#define NAMIDX_CDATAREL 83 // .data.rel.ro
#define NAMIDX_RELTEXT 96 // .rel.text and .rela.text
#define NAMIDX_RELDATA 106 // .rel.data
#define NAMIDX_RELDATA64 107 // .rela.data

if (section_names)
section_names->setsize(sizeof(section_names_init64));
Expand Down Expand Up @@ -738,6 +742,7 @@ Obj *Obj::init(Outbuffer *objbuf, const char *filename, const char *csegname)
elf_newsection2(NAMIDX_COMMENT, SHT_PROGDEF,0, 0,0,0,0,0, 1,0);
elf_newsection2(NAMIDX_NOTE,SHT_NOTE, 0, 0,0,0,0,0, 1,0);
elf_newsection2(NAMIDX_GNUSTACK,SHT_PROGDEF,0, 0,0,0,0,0, 1,0);
elf_newsection2(NAMIDX_CDATAREL,SHT_PROGDEF,SHF_ALLOC|SHF_WRITE,0,0,0,0,0, 16,0);

IDXSTR namidx;
namidx = NAMIDX_TEXT; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx;
Expand All @@ -752,11 +757,12 @@ Obj *Obj::init(Outbuffer *objbuf, const char *filename, const char *csegname)
namidx = NAMIDX_COMMENT; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx;
namidx = NAMIDX_NOTE; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx;
namidx = NAMIDX_GNUSTACK; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx;
namidx = NAMIDX_CDATAREL; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx;
}
else
{
static char section_names_init[] =
"\0.symtab\0.strtab\0.shstrtab\0.text\0.data\0.bss\0.note\0.comment\0.rodata\0.note.GNU-stack\0.rel.text\0.rel.data";
"\0.symtab\0.strtab\0.shstrtab\0.text\0.data\0.bss\0.note\0.comment\0.rodata\0.note.GNU-stack\0.data.rel.ro\0.rel.text\0.rel.data";

if (section_names)
section_names->setsize(sizeof(section_names_init));
Expand Down Expand Up @@ -784,6 +790,7 @@ Obj *Obj::init(Outbuffer *objbuf, const char *filename, const char *csegname)
elf_newsection2(NAMIDX_COMMENT, SHT_PROGDEF,0, 0,0,0,0,0, 1,0);
elf_newsection2(NAMIDX_NOTE,SHT_NOTE, 0, 0,0,0,0,0, 1,0);
elf_newsection2(NAMIDX_GNUSTACK,SHT_PROGDEF,0, 0,0,0,0,0, 1,0);
elf_newsection2(NAMIDX_CDATAREL,SHT_PROGDEF,SHF_ALLOC|SHF_WRITE,0,0,0,0,0, 1,0);

IDXSTR namidx;
namidx = NAMIDX_TEXT; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx;
Expand All @@ -798,6 +805,7 @@ Obj *Obj::init(Outbuffer *objbuf, const char *filename, const char *csegname)
namidx = NAMIDX_COMMENT; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx;
namidx = NAMIDX_NOTE; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx;
namidx = NAMIDX_GNUSTACK; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx;
namidx = NAMIDX_CDATAREL; *(IDXSTR *)section_names_hashtable->get(&namidx) = namidx;
}

if (SYMbuf)
Expand All @@ -816,6 +824,7 @@ Obj *Obj::init(Outbuffer *objbuf, const char *filename, const char *csegname)
elf_addsym(0, 0, 0, STT_SECTION, STB_LOCAL, SHN_RODAT); // STI_RODAT
elf_addsym(0, 0, 0, STT_SECTION, STB_LOCAL, SHN_NOTE); // STI_NOTE
elf_addsym(0, 0, 0, STT_SECTION, STB_LOCAL, SHN_COM); // STI_COM
elf_addsym(0, 0, 0, STT_SECTION, STB_LOCAL, SHN_CDATAREL); // STI_CDATAREL

// Initialize output buffers for CODE, DATA and COMMENTS
// (NOTE not supported, BSS not required)
Expand All @@ -834,6 +843,9 @@ Obj *Obj::init(Outbuffer *objbuf, const char *filename, const char *csegname)
elf_getsegment2(SHN_BSS, STI_BSS, 0);
assert(SegData[UDATA]->SDseg == UDATA);

elf_getsegment2(SHN_CDATAREL, STI_CDATAREL, 0);
assert(SegData[CDATAREL]->SDseg == CDATAREL);

elf_getsegment2(SHN_COM, STI_COM, 0);
assert(SegData[COMD]->SDseg == COMD);

Expand Down Expand Up @@ -1586,11 +1598,13 @@ void Obj::ehtables(Symbol *sfunc,targ_size_t size,Symbol *ehsym)

symbol *ehtab_entry = symbol_generate(SCstatic,type_alloc(TYint));
symbol_keep(ehtab_entry);
ElfObj::getsegment(".deh_beg", NULL, SHT_PROGDEF, SHF_ALLOC, NPTRSIZE);
int seg = ElfObj::getsegment(".deh_eh", NULL, SHT_PROGDEF, SHF_ALLOC, NPTRSIZE);

const int shf_flags = SHF_ALLOC | (config.flags3 & CFG3pic ? SHF_WRITE : 0);
ElfObj::getsegment(".deh_beg", NULL, SHT_PROGDEF, shf_flags, NPTRSIZE);
int seg = ElfObj::getsegment(".deh_eh", NULL, SHT_PROGDEF, shf_flags, NPTRSIZE);
ehtab_entry->Sseg = seg;
Outbuffer *buf = SegData[seg]->SDbuf;
ElfObj::getsegment(".deh_end", NULL, SHT_PROGDEF, SHF_ALLOC, NPTRSIZE);
ElfObj::getsegment(".deh_end", NULL, SHT_PROGDEF, shf_flags, NPTRSIZE);
ehtab_entry->Stype->Tmangle = mTYman_c;
ehsym->Stype->Tmangle = mTYman_c;

Expand All @@ -1608,16 +1622,17 @@ void Obj::ehtables(Symbol *sfunc,targ_size_t size,Symbol *ehsym)

void Obj::ehsections()
{
int sec = ElfObj::getsegment(".deh_beg", NULL, SHT_PROGDEF, SHF_ALLOC, NPTRSIZE);
const int shf_flags = SHF_ALLOC | (config.flags3 & CFG3pic ? SHF_WRITE : 0);
int sec = ElfObj::getsegment(".deh_beg", NULL, SHT_PROGDEF, shf_flags, NPTRSIZE);
//Obj::bytes(sec, 0, 4, NULL);

IDXSTR namidx = Obj::addstr(symtab_strings,"_deh_beg");
elf_addsym(namidx, 0, 4, STT_OBJECT, STB_GLOBAL, MAP_SEG2SECIDX(sec));
//elf_addsym(namidx, 0, 4, STT_OBJECT, STB_GLOBAL, MAP_SEG2SECIDX(sec));

ElfObj::getsegment(".deh_eh", NULL, SHT_PROGDEF, SHF_ALLOC, NPTRSIZE);
ElfObj::getsegment(".deh_eh", NULL, SHT_PROGDEF, shf_flags, NPTRSIZE);

sec = ElfObj::getsegment(".deh_end", NULL, SHT_PROGDEF, SHF_ALLOC, NPTRSIZE);
sec = ElfObj::getsegment(".deh_end", NULL, SHT_PROGDEF, shf_flags, NPTRSIZE);
namidx = Obj::addstr(symtab_strings,"_deh_end");
elf_addsym(namidx, 0, 4, STT_OBJECT, STB_GLOBAL, MAP_SEG2SECIDX(sec));

Expand Down Expand Up @@ -3100,9 +3115,10 @@ void Obj::moduleinfo(Symbol *scc)
const int CFflags = I64 ? (CFoffset64 | CFoff) : CFoff;

{
ElfObj::getsegment(".minfo_beg", NULL, SHT_PROGDEF, SHF_ALLOC, NPTRSIZE);
const int seg = ElfObj::getsegment(".minfo", NULL, SHT_PROGDEF, SHF_ALLOC, NPTRSIZE);
ElfObj::getsegment(".minfo_end", NULL, SHT_PROGDEF, SHF_ALLOC, NPTRSIZE);
const int shf_flags = SHF_ALLOC | (config.flags3 & CFG3pic ? SHF_WRITE : 0);
ElfObj::getsegment(".minfo_beg", NULL, SHT_PROGDEF, shf_flags, NPTRSIZE);
const int seg = ElfObj::getsegment(".minfo", NULL, SHT_PROGDEF, shf_flags, NPTRSIZE);
ElfObj::getsegment(".minfo_end", NULL, SHT_PROGDEF, shf_flags, NPTRSIZE);
SegData[seg]->SDoffset +=
reftoident(seg, SegData[seg]->SDoffset, scc, 0, CFflags);
}
Expand Down Expand Up @@ -3165,21 +3181,23 @@ static void obj_rtinit()
int seg;

{
seg = ElfObj::getsegment(".deh_beg", NULL, SHT_PROGDEF, SHF_ALLOC, NPTRSIZE);
const int shf_flags = SHF_ALLOC | (config.flags3 & CFG3pic ? SHF_WRITE : 0);

seg = ElfObj::getsegment(".deh_beg", NULL, SHT_PROGDEF, shf_flags, NPTRSIZE);
deh_beg = MAP_SEG2SYMIDX(seg);

ElfObj::getsegment(".deh_eh", NULL, SHT_PROGDEF, SHF_ALLOC, NPTRSIZE);
ElfObj::getsegment(".deh_eh", NULL, SHT_PROGDEF, shf_flags, NPTRSIZE);

seg = ElfObj::getsegment(".deh_end", NULL, SHT_PROGDEF, SHF_ALLOC, NPTRSIZE);
seg = ElfObj::getsegment(".deh_end", NULL, SHT_PROGDEF, shf_flags, NPTRSIZE);
deh_end = MAP_SEG2SYMIDX(seg);


seg = ElfObj::getsegment(".minfo_beg", NULL, SHT_PROGDEF, SHF_ALLOC, NPTRSIZE);
seg = ElfObj::getsegment(".minfo_beg", NULL, SHT_PROGDEF, shf_flags, NPTRSIZE);
minfo_beg = MAP_SEG2SYMIDX(seg);

ElfObj::getsegment(".minfo", NULL, SHT_PROGDEF, SHF_ALLOC, NPTRSIZE);
ElfObj::getsegment(".minfo", NULL, SHT_PROGDEF, shf_flags, NPTRSIZE);

seg = ElfObj::getsegment(".minfo_end", NULL, SHT_PROGDEF, SHF_ALLOC, NPTRSIZE);
seg = ElfObj::getsegment(".minfo_end", NULL, SHT_PROGDEF, shf_flags, NPTRSIZE);
minfo_end = MAP_SEG2SYMIDX(seg);
}

Expand Down
9 changes: 8 additions & 1 deletion src/backend/out.c
Expand Up @@ -515,7 +515,14 @@ void out_readonly(symbol *s)
{
// The default is DATA
#if ELFOBJ
s->Sseg = CDATA;
/* Cannot have pointers in CDATA when compiling PIC code, because
* they require dynamic relocations of the read-only segment.
* Instead use the .data.rel.ro section. See Bugzilla 11171.
*/
if (config.flags3 & CFG3pic && dtpointers(s->Sdt))
s->Sseg = CDATAREL;
else
s->Sseg = CDATA;
#endif
#if MACHOBJ
/* Because of PIC and CDATA being in the _TEXT segment;
Expand Down

0 comments on commit 7065361

Please sign in to comment.