mirror of https://github.com/dynup/kpatch
create-klp-module: support unbundled symbols
The create_klp_relasecs_and_syms() function assumes that all dest symbols are bundled, i.e. each symbol is located at offset 0 in its own section. However that may not always be the case. Unbundled symbols can occur, for example, when combining two .o files which have the same bundled symbol. They will be combined into the same section and will no longer be considered "bundled". Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
This commit is contained in:
parent
6c8e90e640
commit
5888f316e6
|
@ -155,9 +155,9 @@ static struct section *find_or_add_klp_relasec(struct kpatch_elf *kelf,
|
||||||
static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section *krelasec,
|
static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section *krelasec,
|
||||||
struct section *ksymsec, char *strings)
|
struct section *ksymsec, char *strings)
|
||||||
{
|
{
|
||||||
struct section *base, *klp_relasec;
|
struct section *klp_relasec;
|
||||||
struct kpatch_relocation *krelas;
|
struct kpatch_relocation *krelas;
|
||||||
struct symbol *sym;
|
struct symbol *sym, *dest;
|
||||||
struct rela *rela;
|
struct rela *rela;
|
||||||
char *objname;
|
char *objname;
|
||||||
int nr, index, offset, toc_offset;
|
int nr, index, offset, toc_offset;
|
||||||
|
@ -207,9 +207,7 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section
|
||||||
*/
|
*/
|
||||||
toc_offset = rela->addend;
|
toc_offset = rela->addend;
|
||||||
|
|
||||||
base = rela->sym->sec;
|
dest = rela->sym;
|
||||||
if (!base)
|
|
||||||
ERROR("base sec of krela not found");
|
|
||||||
|
|
||||||
/* Get the name of the object the rela belongs to */
|
/* Get the name of the object the rela belongs to */
|
||||||
rela = find_rela_by_offset(krelasec->rela,
|
rela = find_rela_by_offset(krelasec->rela,
|
||||||
|
@ -232,8 +230,8 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section
|
||||||
if (!sym)
|
if (!sym)
|
||||||
ERROR("error finding or adding ksym to symtab");
|
ERROR("error finding or adding ksym to symtab");
|
||||||
|
|
||||||
/* Create (or find) the .klp.rela. section for this base sec and object */
|
/* Create (or find) the .klp.rela. section for this dest sec and object */
|
||||||
klp_relasec = find_or_add_klp_relasec(kelf, base, objname);
|
klp_relasec = find_or_add_klp_relasec(kelf, dest->sec, objname);
|
||||||
if (!klp_relasec)
|
if (!klp_relasec)
|
||||||
ERROR("error finding or adding klp relasec");
|
ERROR("error finding or adding klp relasec");
|
||||||
|
|
||||||
|
@ -241,10 +239,10 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section
|
||||||
ALLOC_LINK(rela, &klp_relasec->relas);
|
ALLOC_LINK(rela, &klp_relasec->relas);
|
||||||
rela->sym = sym;
|
rela->sym = sym;
|
||||||
rela->type = krelas[index].type;
|
rela->type = krelas[index].type;
|
||||||
if (!strcmp(base->name, ".toc"))
|
if (!strcmp(dest->sec->name, ".toc"))
|
||||||
rela->offset = toc_offset;
|
rela->offset = toc_offset;
|
||||||
else
|
else
|
||||||
rela->offset = krelas[index].offset;
|
rela->offset = krelas[index].offset + dest->sym.st_value;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GCC 6+ adds 0x8 to the offset of every local function entry
|
* GCC 6+ adds 0x8 to the offset of every local function entry
|
||||||
|
@ -253,7 +251,7 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section
|
||||||
* local function becomes global, we don't want to skip the
|
* local function becomes global, we don't want to skip the
|
||||||
* .toc setup anymore.
|
* .toc setup anymore.
|
||||||
*/
|
*/
|
||||||
if (!strcmp(base->name, ".toc") &&
|
if (!strcmp(dest->sec->name, ".toc") &&
|
||||||
rela->sym->type == STT_FUNC && rela->sym->bind == STB_LOCAL) {
|
rela->sym->type == STT_FUNC && rela->sym->bind == STB_LOCAL) {
|
||||||
rela->addend = 0;
|
rela->addend = 0;
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue