[Ltrace-devel] [PATCH v2] xtensa: add xtensa support
Petr Machata
pmachata at redhat.com
Fri Jan 2 01:32:16 UTC 2015
Max Filippov <jcmvbkbc at gmail.com> writes:
> - drop gimme_arg and implement arch_fetch_* callbacks;
Cool.
> - add diagnostics to {get,set}_instruction_pointer, get_stack_pointer
> and get_return_addr;
> - update CREDITS, NEWS and README.
>
> Changes RFC->PATCH:
> - adopt PLT unresolving algorithm used by PPC
Also cool.
> +int
> +arch_elf_init(struct ltelf *lte, struct library *lib)
> +{
> + Elf_Scn *scn;
> + GElf_Shdr shdr;
> + GElf_Addr relplt_addr;
> + GElf_Xword relplt_size;
> + GElf_Phdr phdr;
> + size_t i;
> +
> + for (i = 0; gelf_getphdr(lte->elf, i, &phdr) != NULL; ++i) {
> + if (phdr.p_type == PT_LOAD) {
> + lib->arch.loadable_sz =
> + phdr.p_vaddr + phdr.p_memsz - lte->bias;
Was this tested on a prelinked system? It's confusing that you subtract
bias to get from ELF address to memory address. Normally you would add
it.
Also, correct me if I'm wrong, but loadable_sz actually points to the
end of the region, and hence is not a size. Would loadable_end be a
better name?
> + if (elf_get_section_type(lte, SHT_DYNAMIC, &scn, &shdr) < 0
> + || scn == NULL) {
> + fail:
> + error(0, 0, "Couldn't get SHT_DYNAMIC: %s",
> + elf_errmsg(-1));
> + return -1;
> + }
> +
> + Elf_Data *data = elf_loaddata(scn, &shdr);
> + if (data == NULL)
> + goto fail;
> +
> + for (i = 0; i < shdr.sh_size / shdr.sh_entsize; ++i) {
> + GElf_Dyn dyn;
> +
> + if (gelf_getdyn(data, i, &dyn) == NULL)
> + goto fail;
> +
> + if (dyn.d_tag == DT_JMPREL) {
> + relplt_addr = dyn.d_un.d_ptr;
> + } else if (dyn.d_tag == DT_PLTRELSZ) {
> + relplt_size = dyn.d_un.d_val;
> + }
> + }
Would calling elf_load_dynamic_entry twice be suitable instead of the
above block?
The two calls would end up looking up the section by type twice. That
has negative performance implications. I suspect they are negligible,
but should you care, would you be also willing to contribute a patch
that implements on-demand caching of SHT_DYNAMIC inside
elf_load_dynamic_entry?
> + for (i = 1; i < lte->ehdr.e_shnum; ++i) {
> + Elf_Scn *scn;
> + GElf_Shdr shdr;
> +
> + scn = elf_getscn(lte->elf, i);
> + if (scn == NULL || gelf_getshdr(scn, &shdr) == NULL) {
> + fprintf(stderr, "Couldn't get section header: %s\n",
> + elf_errmsg(-1));
> + exit(EXIT_FAILURE);
> + }
> + if (shdr.sh_addr == relplt_addr
> + && shdr.sh_size == relplt_size) {
To get the section pointed to by DT_JMPREL, you could call
elf_get_section_covering and then check the size in the returned shdr.
My thinking is that if there is more than one section covering a given
address, the ELF is probably not structurally sound, and you can safely
bail out anyway.
FWIW, the ARM backend simply does this:
GElf_Addr jmprel_addr;
Elf_Scn *jmprel_sec;
GElf_Shdr jmprel_shdr;
if (elf_load_dynamic_entry(lte, DT_JMPREL, &jmprel_addr) < 0
|| elf_get_section_covering(lte, jmprel_addr,
&jmprel_sec, &jmprel_shdr) < 0
|| jmprel_sec == NULL)
return -1;
Other than these things, the code looks solid as far as I can tell (not
that I know anything about xtensa though ;) ).
Thanks,
Petr
More information about the Ltrace-devel
mailing list