struct-init: Copy relocs for compound literals

When copying the content of compound literals we must
include relocations as well.
This commit is contained in:
Michael Matz 2016-10-03 19:21:10 +02:00
parent 0bca6cab06
commit 7ab35c6265
2 changed files with 55 additions and 0 deletions

View File

@ -5995,9 +5995,35 @@ static void init_putv(CType *type, Section *sec, unsigned long c)
/* These come from compound literals, memcpy stuff over. */
Section *ssec;
ElfW(Sym) *esym;
ElfW_Rel *rel;
esym = &((ElfW(Sym) *)symtab_section->data)[vtop->sym->c];
ssec = tcc_state->sections[esym->st_shndx];
memmove (ptr, ssec->data + esym->st_value, size);
if (ssec->reloc) {
/* We need to copy over all memory contents, and that
includes relocations. Use the fact that relocs are
created it order, so look from the end of relocs
until we hit one before the copied region. */
int num_relocs = ssec->reloc->data_offset / sizeof(*rel);
rel = (ElfW_Rel*)(ssec->reloc->data + ssec->reloc->data_offset);
while (num_relocs--) {
rel--;
if (rel->r_offset >= esym->st_value + size)
continue;
if (rel->r_offset < esym->st_value)
break;
put_elf_reloca(symtab_section, sec,
c + rel->r_offset - esym->st_value,
ELFW(R_TYPE)(rel->r_info),
ELFW(R_SYM)(rel->r_info),
#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
rel->r_addend
#else
0
#endif
);
}
}
} else {
if ((vtop->r & VT_SYM) &&
(bt == VT_BYTE ||

View File

@ -109,6 +109,21 @@ struct pkthdr {
struct in6_addr daddr, saddr;
};
struct pkthdr phdr = { { { 6,5,4,3 } }, { { 9,8,7,6 } } };
struct Wrap {
void *func;
};
int global;
void inc_global (void)
{
global++;
}
struct Wrap global_wrap[] = {
((struct Wrap) {inc_global}),
inc_global,
};
#include <stdio.h>
void print_ (const char *name, const u8 *p, long size)
{
@ -171,6 +186,19 @@ void foo (struct W *w, struct pkthdr *phdr_)
}
#endif
void test_compound_with_relocs (void)
{
struct Wrap local_wrap[] = {
((struct Wrap) {inc_global}),
inc_global,
};
void (*p)(void);
p = global_wrap[0].func; p();
p = global_wrap[1].func; p();
p = local_wrap[0].func; p();
p = local_wrap[1].func; p();
}
int main()
{
print(ce);
@ -195,5 +223,6 @@ int main()
print(phdr);
foo(&gw, &phdr);
//printf("q: %s\n", q);
test_compound_with_relocs();
return 0;
}