From: Max Filippov <jcmvbkbc@gmail.com>
To: gcc-patches@gcc.gnu.org
Cc: Ian Lance Taylor <ian@airs.com>, Max Filippov <jcmvbkbc@gmail.com>
Subject: [RFC 1/2] libbacktrace: add FDPIC support
Date: Sun, 26 May 2024 23:50:25 -0700 [thread overview]
Message-ID: <20240527065026.855607-2-jcmvbkbc@gmail.com> (raw)
In-Reply-To: <20240527065026.855607-1-jcmvbkbc@gmail.com>
Instead of a single base address FDPIC ELF files use load map: a
structure with an array of mappings for individual segments. Change
libbacktrace functions and structures to support that.
libbacktrace/
PR libbacktrace/114941
* dwarf.c: Include <link.h> or <sys/link.h> if available.
(struct dwarf_data): Change base_address type to base_address_type.
(add_low_high_range): Change base_address argument type to
base_address_type. Use __RELOC_UINTPTR for lowpc and highpc
calculation.
(add_ranges_from_ranges): Change base_address argument type to
base_address_type. Use __RELOC_UINTPTR to calculate arguments
for add_range().
(add_ranges_from_rnglists): Change base_address argument type to
base_address_type. Use __RELOC_UINTPTR to calculate arguments
for add_range(). Use __RELOC_UINTPTR for low calculation.
(add_ranges, find_address_ranges, build_address_map): Change
base_address argument type to base_address_type.
(add_line): Use __RELOC_UINTPTR for ln->pc calculation.
(build_dwarf_data, backtrace_dwarf_add): Change base_address
argument type to base_address_type.
* elf.c (elf_initialize_syminfo): Change base_address argument
type to base_address_type. Use __RELOC_UINTPTR for
elf_symbols[j].address calculation.
(elf_add): Change base_address argument type to
base_address_type. Do early return -1 in case of FDPIC
executable, update corresponding comment.
(backtrace_initialize): Change NULL base address parameter in
the add_elf() call to no_base_address.
* internal.h (base_address_type, __RELOC_POINTER)
(__RELOC_UINTPTR, no_base_address): New definitions.
(backtrace_dwarf_add): Change base_address argument type to
base_address_type.
---
libbacktrace/dwarf.c | 60 ++++++++++++++++++++++++-----------------
libbacktrace/elf.c | 20 +++++++++-----
libbacktrace/internal.h | 14 +++++++++-
3 files changed, 62 insertions(+), 32 deletions(-)
diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
index ed0672964c24..bcab23562e2a 100644
--- a/libbacktrace/dwarf.c
+++ b/libbacktrace/dwarf.c
@@ -43,6 +43,15 @@ POSSIBILITY OF SUCH DAMAGE. */
#include "backtrace.h"
#include "internal.h"
+#ifdef __FDPIC__
+ #ifdef HAVE_LINK_H
+ #include <link.h>
+ #endif
+ #ifdef HAVE_SYS_LINK_H
+ #include <sys/link.h>
+ #endif
+#endif
+
#if !defined(HAVE_DECL_STRNLEN) || !HAVE_DECL_STRNLEN
/* If strnlen is not declared, provide our own version. */
@@ -389,7 +398,7 @@ struct dwarf_data
/* The data for .gnu_debugaltlink. */
struct dwarf_data *altlink;
/* The base address for this file. */
- uintptr_t base_address;
+ base_address_type base_address;
/* A sorted list of address ranges. */
struct unit_addrs *addrs;
/* Number of address ranges in list. */
@@ -1610,7 +1619,7 @@ update_pcrange (const struct attr* attr, const struct attr_val* val,
static int
add_low_high_range (struct backtrace_state *state,
const struct dwarf_sections *dwarf_sections,
- uintptr_t base_address, int is_bigendian,
+ base_address_type base_address, int is_bigendian,
struct unit *u, const struct pcrange *pcrange,
int (*add_range) (struct backtrace_state *state,
void *rdata, uintptr_t lowpc,
@@ -1646,8 +1655,8 @@ add_low_high_range (struct backtrace_state *state,
/* Add in the base address of the module when recording PC values,
so that we can look up the PC directly. */
- lowpc += base_address;
- highpc += base_address;
+ lowpc = __RELOC_UINTPTR (lowpc, base_address);
+ highpc = __RELOC_UINTPTR (highpc, base_address);
return add_range (state, rdata, lowpc, highpc, error_callback, data, vec);
}
@@ -1659,7 +1668,7 @@ static int
add_ranges_from_ranges (
struct backtrace_state *state,
const struct dwarf_sections *dwarf_sections,
- uintptr_t base_address, int is_bigendian,
+ base_address_type base_address, int is_bigendian,
struct unit *u, uintptr_t base,
const struct pcrange *pcrange,
int (*add_range) (struct backtrace_state *state, void *rdata,
@@ -1706,8 +1715,8 @@ add_ranges_from_ranges (
else
{
if (!add_range (state, rdata,
- (uintptr_t) low + base + base_address,
- (uintptr_t) high + base + base_address,
+ __RELOC_UINTPTR (low + base, base_address),
+ __RELOC_UINTPTR (high + base, base_address),
error_callback, data, vec))
return 0;
}
@@ -1726,7 +1735,7 @@ static int
add_ranges_from_rnglists (
struct backtrace_state *state,
const struct dwarf_sections *dwarf_sections,
- uintptr_t base_address, int is_bigendian,
+ base_address_type base_address, int is_bigendian,
struct unit *u, uintptr_t base,
const struct pcrange *pcrange,
int (*add_range) (struct backtrace_state *state, void *rdata,
@@ -1809,9 +1818,9 @@ add_ranges_from_rnglists (
u->addrsize, is_bigendian, index,
error_callback, data, &high))
return 0;
- if (!add_range (state, rdata, low + base_address,
- high + base_address, error_callback, data,
- vec))
+ if (!add_range (state, rdata, __RELOC_UINTPTR (low, base_address),
+ __RELOC_UINTPTR (high, base_address),
+ error_callback, data, vec))
return 0;
}
break;
@@ -1828,7 +1837,7 @@ add_ranges_from_rnglists (
error_callback, data, &low))
return 0;
length = read_uleb128 (&rnglists_buf);
- low += base_address;
+ low = __RELOC_UINTPTR (low, base_address);
if (!add_range (state, rdata, low, low + length,
error_callback, data, vec))
return 0;
@@ -1842,8 +1851,9 @@ add_ranges_from_rnglists (
low = read_uleb128 (&rnglists_buf);
high = read_uleb128 (&rnglists_buf);
- if (!add_range (state, rdata, low + base + base_address,
- high + base + base_address,
+ if (!add_range (state, rdata,
+ __RELOC_UINTPTR (low + base, base_address),
+ __RELOC_UINTPTR (high + base, base_address),
error_callback, data, vec))
return 0;
}
@@ -1860,9 +1870,9 @@ add_ranges_from_rnglists (
low = (uintptr_t) read_address (&rnglists_buf, u->addrsize);
high = (uintptr_t) read_address (&rnglists_buf, u->addrsize);
- if (!add_range (state, rdata, low + base_address,
- high + base_address, error_callback, data,
- vec))
+ if (!add_range (state, rdata, __RELOC_UINTPTR (low, base_address),
+ __RELOC_UINTPTR (high, base_address),
+ error_callback, data, vec))
return 0;
}
break;
@@ -1874,7 +1884,7 @@ add_ranges_from_rnglists (
low = (uintptr_t) read_address (&rnglists_buf, u->addrsize);
length = (uintptr_t) read_uleb128 (&rnglists_buf);
- low += base_address;
+ low = __RELOC_UINTPTR (low, base_address);
if (!add_range (state, rdata, low, low + length,
error_callback, data, vec))
return 0;
@@ -1902,7 +1912,7 @@ add_ranges_from_rnglists (
static int
add_ranges (struct backtrace_state *state,
const struct dwarf_sections *dwarf_sections,
- uintptr_t base_address, int is_bigendian,
+ base_address_type base_address, int is_bigendian,
struct unit *u, uintptr_t base, const struct pcrange *pcrange,
int (*add_range) (struct backtrace_state *state, void *rdata,
uintptr_t lowpc, uintptr_t highpc,
@@ -1938,7 +1948,8 @@ add_ranges (struct backtrace_state *state,
read, 0 if there is some error. */
static int
-find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
+find_address_ranges (struct backtrace_state *state,
+ base_address_type base_address,
struct dwarf_buf *unit_buf,
const struct dwarf_sections *dwarf_sections,
int is_bigendian, struct dwarf_data *altlink,
@@ -2093,7 +2104,8 @@ find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
on success, 0 on failure. */
static int
-build_address_map (struct backtrace_state *state, uintptr_t base_address,
+build_address_map (struct backtrace_state *state,
+ base_address_type base_address,
const struct dwarf_sections *dwarf_sections,
int is_bigendian, struct dwarf_data *altlink,
backtrace_error_callback error_callback, void *data,
@@ -2312,7 +2324,7 @@ add_line (struct backtrace_state *state, struct dwarf_data *ddata,
/* Add in the base address here, so that we can look up the PC
directly. */
- ln->pc = pc + ddata->base_address;
+ ln->pc = __RELOC_UINTPTR (pc, ddata->base_address);
ln->filename = filename;
ln->lineno = lineno;
@@ -3951,7 +3963,7 @@ dwarf_fileline (struct backtrace_state *state, uintptr_t pc,
static struct dwarf_data *
build_dwarf_data (struct backtrace_state *state,
- uintptr_t base_address,
+ base_address_type base_address,
const struct dwarf_sections *dwarf_sections,
int is_bigendian,
struct dwarf_data *altlink,
@@ -4009,7 +4021,7 @@ build_dwarf_data (struct backtrace_state *state,
int
backtrace_dwarf_add (struct backtrace_state *state,
- uintptr_t base_address,
+ base_address_type base_address,
const struct dwarf_sections *dwarf_sections,
int is_bigendian,
struct dwarf_data *fileline_altlink,
diff --git a/libbacktrace/elf.c b/libbacktrace/elf.c
index 3cd87020b031..c2d18b4a398e 100644
--- a/libbacktrace/elf.c
+++ b/libbacktrace/elf.c
@@ -633,7 +633,7 @@ elf_symbol_search (const void *vkey, const void *ventry)
static int
elf_initialize_syminfo (struct backtrace_state *state,
- uintptr_t base_address,
+ base_address_type base_address,
const unsigned char *symtab_data, size_t symtab_size,
const unsigned char *strtab, size_t strtab_size,
backtrace_error_callback error_callback,
@@ -699,7 +699,7 @@ elf_initialize_syminfo (struct backtrace_state *state,
= *(const b_elf_addr *) (opd->data + (sym->st_value - opd->addr));
else
elf_symbols[j].address = sym->st_value;
- elf_symbols[j].address += base_address;
+ elf_symbols[j].address = __RELOC_UINTPTR (elf_symbols[j].address, base_address);
elf_symbols[j].size = sym->st_size;
++j;
}
@@ -6506,7 +6506,7 @@ backtrace_uncompress_lzma (struct backtrace_state *state,
static int
elf_add (struct backtrace_state *state, const char *filename, int descriptor,
const unsigned char *memory, size_t memory_size,
- uintptr_t base_address, struct elf_ppc64_opd_data *caller_opd,
+ base_address_type base_address, struct elf_ppc64_opd_data *caller_opd,
backtrace_error_callback error_callback, void *data,
fileline *fileline_fn, int *found_sym, int *found_dwarf,
struct dwarf_data **fileline_entry, int exe, int debuginfo,
@@ -6636,9 +6636,15 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
/* If the executable is ET_DYN, it is either a PIE, or we are running
directly a shared library with .interp. We need to wait for
- dl_iterate_phdr in that case to determine the actual base_address. */
+ dl_iterate_phdr in that case to determine the actual base_address.
+ In case of FDPIC we always need the actual base_address. */
+#ifndef __FDPIC__
if (exe && ehdr.e_type == ET_DYN)
return -1;
+#else
+ if (exe)
+ return -1;
+#endif
shoff = ehdr.e_shoff;
shnum = ehdr.e_shnum;
@@ -7413,9 +7419,9 @@ backtrace_initialize (struct backtrace_state *state, const char *filename,
fileline elf_fileline_fn = elf_nodebug;
struct phdr_data pd;
- ret = elf_add (state, filename, descriptor, NULL, 0, 0, NULL, error_callback,
- data, &elf_fileline_fn, &found_sym, &found_dwarf, NULL, 1, 0,
- NULL, 0);
+ ret = elf_add (state, filename, descriptor, NULL, 0, no_base_address, NULL,
+ error_callback, data, &elf_fileline_fn, &found_sym,
+ &found_dwarf, NULL, 1, 0, NULL, 0);
if (!ret)
return 0;
diff --git a/libbacktrace/internal.h b/libbacktrace/internal.h
index 4fa0af8cb6c9..456911166026 100644
--- a/libbacktrace/internal.h
+++ b/libbacktrace/internal.h
@@ -323,10 +323,22 @@ struct dwarf_sections
struct dwarf_data;
+#if defined (HAVE_DL_ITERATE_PHDR) && defined (__FDPIC__)
+typedef struct elf32_fdpic_loadaddr base_address_type;
+#define __RELOC_UINTPTR(ptr, base) ((uintptr_t)__RELOC_POINTER (ptr, base))
+#define no_base_address ((struct elf32_fdpic_loadaddr){0})
+#else
+typedef uintptr_t base_address_type;
+#define __RELOC_POINTER(ptr, base) ((ptr) + (base))
+#define __RELOC_UINTPTR(ptr, base) ((uintptr_t)__RELOC_POINTER (ptr, base))
+#define no_base_address ((uintptr_t)0)
+#endif
+
+
/* Add file/line information for a DWARF module. */
extern int backtrace_dwarf_add (struct backtrace_state *state,
- uintptr_t base_address,
+ base_address_type base_address,
const struct dwarf_sections *dwarf_sections,
int is_bigendian,
struct dwarf_data *fileline_altlink,
--
2.39.2
next prev parent reply other threads:[~2024-05-27 6:50 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-05-27 6:50 [RFC 0/2] " Max Filippov
2024-05-27 6:50 ` Max Filippov [this message]
2024-06-11 16:54 ` [RFC 1/2] " Max Filippov
2024-05-27 6:50 ` [RFC 2/2] libstdc++-v3/src/libbacktrace: add -funwind-tables Max Filippov
2024-05-27 7:01 ` [RFC 0/2] libbacktrace: add FDPIC support Rainer Orth
2024-05-27 7:12 ` Max Filippov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240527065026.855607-2-jcmvbkbc@gmail.com \
--to=jcmvbkbc@gmail.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=ian@airs.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).