Merge pull request #8421 from opensourcerouting/xrelfo-arm

fix xrelfo on ARM(32) & cross-compile
This commit is contained in:
Mark Stapp 2021-04-12 08:07:05 -04:00 committed by GitHub
commit 53c42c82de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 124 additions and 24 deletions

View File

@ -1032,7 +1032,7 @@ static char *elfdata_strptr(Elf_Data *data, size_t offset)
static void elffile_add_dynreloc(struct elffile *w, Elf_Data *reldata, static void elffile_add_dynreloc(struct elffile *w, Elf_Data *reldata,
size_t entries, Elf_Data *symdata, size_t entries, Elf_Data *symdata,
Elf_Data *strdata) Elf_Data *strdata, Elf_Type typ)
{ {
size_t i; size_t i;
@ -1041,12 +1041,59 @@ static void elffile_add_dynreloc(struct elffile *w, Elf_Data *reldata,
size_t symidx; size_t symidx;
GElf_Rela *rela; GElf_Rela *rela;
GElf_Sym *sym; GElf_Sym *sym;
GElf_Addr rel_offs = 0;
relw = (struct elfreloc *)typeobj_elfreloc.tp_alloc( relw = (struct elfreloc *)typeobj_elfreloc.tp_alloc(
&typeobj_elfreloc, 0); &typeobj_elfreloc, 0);
relw->ef = w; relw->ef = w;
rela = relw->rela = gelf_getrela(reldata, i, &relw->_rela); if (typ == ELF_T_REL) {
GElf_Rel _rel, *rel;
GElf_Addr offs;
rel = gelf_getrel(reldata, i, &_rel);
relw->rela = &relw->_rela;
relw->rela->r_offset = rel->r_offset;
relw->rela->r_info = rel->r_info;
relw->rela->r_addend = 0;
relw->relative = true;
/* REL uses the pointer contents itself instead of the
* RELA addend field :( ... theoretically this could
* be some weird platform specific encoding, but since
* we only care about data relocations it should
* always be a pointer...
*/
if (elffile_virt2file(w, rel->r_offset, &offs)) {
Elf_Data *ptr, *conv;
GElf_Addr tmp;
Elf_Data mem = {
.d_buf = (void *)&tmp,
.d_type = ELF_T_ADDR,
.d_version = EV_CURRENT,
.d_size = sizeof(tmp),
.d_off = 0,
.d_align = 0,
};
ptr = elf_getdata_rawchunk(w->elf, offs,
w->elfclass / 8,
ELF_T_ADDR);
conv = gelf_xlatetom(w->elf, &mem, ptr,
w->mmap[EI_DATA]);
if (conv) {
memcpy(&rel_offs, conv->d_buf,
conv->d_size);
relw->relative = false;
relw->rela->r_addend = rel_offs;
}
}
} else
relw->rela = gelf_getrela(reldata, i, &relw->_rela);
rela = relw->rela;
symidx = relw->symidx = GELF_R_SYM(rela->r_info); symidx = relw->symidx = GELF_R_SYM(rela->r_info);
sym = relw->sym = gelf_getsym(symdata, symidx, &relw->_sym); sym = relw->sym = gelf_getsym(symdata, symidx, &relw->_sym);
if (sym) { if (sym) {
@ -1062,9 +1109,16 @@ static void elffile_add_dynreloc(struct elffile *w, Elf_Data *reldata,
relw->st_value = 0; relw->st_value = 0;
} }
debugf("dynreloc @ %016llx sym %5llu %016llx %s\n", if (typ == ELF_T_RELA)
(long long)rela->r_offset, (unsigned long long)symidx, debugf("dynrela @ %016llx sym %5llu %016llx %s\n",
(long long)rela->r_offset,
(unsigned long long)symidx,
(long long)rela->r_addend, relw->symname); (long long)rela->r_addend, relw->symname);
else
debugf("dynrel @ %016llx sym %5llu (%016llx) %s\n",
(long long)rela->r_offset,
(unsigned long long)symidx,
(unsigned long long)rel_offs, relw->symname);
elfrelocs_add(&w->dynrelocs, relw); elfrelocs_add(&w->dynrelocs, relw);
} }
@ -1166,8 +1220,10 @@ static PyObject *elffile_load(PyTypeObject *type, PyObject *args,
Elf_Data *dyndata = elf_getdata_rawchunk(w->elf, Elf_Data *dyndata = elf_getdata_rawchunk(w->elf,
phdr->p_offset, phdr->p_filesz, ELF_T_DYN); phdr->p_offset, phdr->p_filesz, ELF_T_DYN);
GElf_Addr dynrela = 0, symtab = 0, strtab = 0; GElf_Addr dynrela = 0, dynrel = 0, symtab = 0, strtab = 0;
size_t dynrelasz = 0, dynrelaent = 0, strsz = 0; size_t dynrelasz = 0, dynrelaent = 0;
size_t dynrelsz = 0, dynrelent = 0;
size_t strsz = 0;
GElf_Dyn _dyn, *dyn; GElf_Dyn _dyn, *dyn;
for (size_t j = 0;; j++) { for (size_t j = 0;; j++) {
@ -1198,16 +1254,20 @@ static PyObject *elffile_load(PyTypeObject *type, PyObject *args,
dynrelaent = dyn->d_un.d_val; dynrelaent = dyn->d_un.d_val;
break; break;
case DT_REL:
dynrel = dyn->d_un.d_ptr;
break;
case DT_RELSZ: case DT_RELSZ:
if (dyn->d_un.d_val) dynrelsz = dyn->d_un.d_val;
fprintf(stderr, break;
"WARNING: ignoring non-empty DT_REL!\n"); case DT_RELENT:
dynrelent = dyn->d_un.d_val;
break; break;
} }
} }
GElf_Addr offset; GElf_Addr offset;
Elf_Data *symdata = NULL, *strdata = NULL, *reladata = NULL; Elf_Data *symdata = NULL, *strdata = NULL;
if (elffile_virt2file(w, symtab, &offset)) if (elffile_virt2file(w, symtab, &offset))
symdata = elf_getdata_rawchunk(w->elf, offset, symdata = elf_getdata_rawchunk(w->elf, offset,
@ -1217,19 +1277,37 @@ static PyObject *elffile_load(PyTypeObject *type, PyObject *args,
strdata = elf_getdata_rawchunk(w->elf, offset, strdata = elf_getdata_rawchunk(w->elf, offset,
strsz, ELF_T_BYTE); strsz, ELF_T_BYTE);
if (!dynrela || !dynrelasz || !dynrelaent) size_t c;
continue;
if (!elffile_virt2file(w, dynrela, &offset)) if (dynrela && dynrelasz && dynrelaent
continue; && elffile_virt2file(w, dynrela, &offset)) {
Elf_Data *reladata = NULL;
debugf("dynrela @%llx/%llx+%llx\n", (long long)dynrela, debugf("dynrela @%llx/%llx+%llx\n", (long long)dynrela,
(long long)offset, (long long)dynrelasz); (long long)offset, (long long)dynrelasz);
reladata = elf_getdata_rawchunk(w->elf, offset, dynrelasz, reladata = elf_getdata_rawchunk(w->elf, offset,
dynrelasz, ELF_T_RELA);
c = dynrelasz / dynrelaent;
elffile_add_dynreloc(w, reladata, c, symdata, strdata,
ELF_T_RELA); ELF_T_RELA);
elffile_add_dynreloc(w, reladata, dynrelasz / dynrelaent, }
symdata, strdata);
if (dynrel && dynrelsz && dynrelent
&& elffile_virt2file(w, dynrel, &offset)) {
Elf_Data *reldata = NULL;
debugf("dynrel @%llx/%llx+%llx\n", (long long)dynrel,
(long long)offset, (long long)dynrelsz);
reldata = elf_getdata_rawchunk(w->elf, offset, dynrelsz,
ELF_T_REL);
c = dynrelsz / dynrelent;
elffile_add_dynreloc(w, reldata, c, symdata, strdata,
ELF_T_REL);
}
} }
#endif #endif

View File

@ -22,7 +22,6 @@ pathd_libpath_a_SOURCES = \
pathd/path_cli.c \ pathd/path_cli.c \
pathd/path_debug.c \ pathd/path_debug.c \
pathd/path_errors.c \ pathd/path_errors.c \
pathd/path_main.c \
pathd/path_nb.c \ pathd/path_nb.c \
pathd/path_nb_config.c \ pathd/path_nb_config.c \
pathd/path_nb_state.c \ pathd/path_nb_state.c \
@ -50,7 +49,9 @@ noinst_HEADERS += \
pathd/pathd.h \ pathd/pathd.h \
# end # end
pathd_pathd_SOURCES = pathd/path_main.c pathd_pathd_SOURCES = \
pathd/path_main.c \
# end
nodist_pathd_pathd_SOURCES = \ nodist_pathd_pathd_SOURCES = \
yang/frr-pathd.yang.c \ yang/frr-pathd.yang.c \
# end # end

View File

@ -25,6 +25,15 @@
* Encoding and decoding for PCEP Object TLVs. * Encoding and decoding for PCEP Object TLVs.
*/ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef __FreeBSD__
#include <sys/endian.h>
#else
#include <endian.h>
#endif /* __FreeBSD__ */
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>

View File

@ -21,6 +21,15 @@
*/ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef __FreeBSD__
#include <sys/endian.h>
#else
#include <endian.h>
#endif /* __FreeBSD__ */
#include <stdlib.h> #include <stdlib.h>
#include <CUnit/CUnit.h> #include <CUnit/CUnit.h>

View File

@ -162,7 +162,10 @@ class ELFDissectData(object):
for field in parent._efields[self.elfclass]: for field in parent._efields[self.elfclass]:
if field[0] == fieldname: if field[0] == fieldname:
break break
offset += struct.calcsize(field[1]) spec = field[1]
if spec == 'P':
spec = 'I' if self.elfclass == 32 else 'Q'
offset += struct.calcsize(spec)
else: else:
raise AttributeError('%r not found in %r.fields' % (fieldname, parent)) raise AttributeError('%r not found in %r.fields' % (fieldname, parent))