summaryrefslogtreecommitdiff
path: root/absl/debugging/symbolize_elf.inc
diff options
context:
space:
mode:
Diffstat (limited to 'absl/debugging/symbolize_elf.inc')
-rw-r--r--absl/debugging/symbolize_elf.inc67
1 files changed, 60 insertions, 7 deletions
diff --git a/absl/debugging/symbolize_elf.inc b/absl/debugging/symbolize_elf.inc
index f4d5727b..9bfdd915 100644
--- a/absl/debugging/symbolize_elf.inc
+++ b/absl/debugging/symbolize_elf.inc
@@ -77,6 +77,10 @@
#include "absl/debugging/internal/vdso_support.h"
#include "absl/strings/string_view.h"
+#if defined(__FreeBSD__) && !defined(ElfW)
+#define ElfW(x) __ElfN(x)
+#endif
+
namespace absl {
ABSL_NAMESPACE_BEGIN
@@ -319,6 +323,7 @@ class Symbolizer {
const ptrdiff_t relocation,
char *out, int out_size,
char *tmp_buf, int tmp_buf_size);
+ const char *GetUncachedSymbol(const void *pc);
enum {
SYMBOL_BUF_SIZE = 3072,
@@ -701,6 +706,16 @@ static ABSL_ATTRIBUTE_NOINLINE FindSymbolResult FindSymbol(
const char *start_address =
ComputeOffset(original_start_address, relocation);
+#ifdef __arm__
+ // ARM functions are always aligned to multiples of two bytes; the
+ // lowest-order bit in start_address is ignored by the CPU and indicates
+ // whether the function contains ARM (0) or Thumb (1) code. We don't care
+ // about what encoding is being used; we just want the real start address
+ // of the function.
+ start_address = reinterpret_cast<const char *>(
+ reinterpret_cast<uintptr_t>(start_address) & ~1);
+#endif
+
if (deref_function_descriptor_pointer &&
InSection(original_start_address, opd)) {
// The opd section is mapped into memory. Just dereference
@@ -1131,6 +1146,14 @@ bool Symbolizer::RegisterObjFile(const char *filename,
reinterpret_cast<uintptr_t>(old->end_addr), old->filename);
}
return true;
+ } else if (old->end_addr == start_addr &&
+ reinterpret_cast<uintptr_t>(old->start_addr) - old->offset ==
+ reinterpret_cast<uintptr_t>(start_addr) - offset &&
+ strcmp(old->filename, filename) == 0) {
+ // Two contiguous map entries that span a contiguous region of the file,
+ // perhaps because some part of the file was mlock()ed. Combine them.
+ old->end_addr = end_addr;
+ return true;
}
}
ObjFile *obj = impl->addr_map_.Add();
@@ -1319,13 +1342,7 @@ static bool MaybeInitializeObjFile(ObjFile *obj) {
// they are called here as well.
// To keep stack consumption low, we would like this function to not
// get inlined.
-const char *Symbolizer::GetSymbol(const void *const pc) {
- const char *entry = FindSymbolInCache(pc);
- if (entry != nullptr) {
- return entry;
- }
- symbol_buf_[0] = '\0';
-
+const char *Symbolizer::GetUncachedSymbol(const void *pc) {
ObjFile *const obj = FindObjFile(pc, 1);
ptrdiff_t relocation = 0;
int fd = -1;
@@ -1413,6 +1430,42 @@ const char *Symbolizer::GetSymbol(const void *const pc) {
return InsertSymbolInCache(pc, symbol_buf_);
}
+const char *Symbolizer::GetSymbol(const void *pc) {
+ const char *entry = FindSymbolInCache(pc);
+ if (entry != nullptr) {
+ return entry;
+ }
+ symbol_buf_[0] = '\0';
+
+#ifdef __hppa__
+ {
+ // In some contexts (e.g., return addresses), PA-RISC uses the lowest two
+ // bits of the address to indicate the privilege level. Clear those bits
+ // before trying to symbolize.
+ const auto pc_bits = reinterpret_cast<uintptr_t>(pc);
+ const auto address = pc_bits & ~0x3;
+ entry = GetUncachedSymbol(reinterpret_cast<const void *>(address));
+ if (entry != nullptr) {
+ return entry;
+ }
+
+ // In some contexts, PA-RISC also uses bit 1 of the address to indicate that
+ // this is a cross-DSO function pointer. Such function pointers actually
+ // point to a procedure label, a struct whose first 32-bit (pointer) element
+ // actually points to the function text. With no symbol found for this
+ // address so far, try interpreting it as a cross-DSO function pointer and
+ // see how that goes.
+ if (pc_bits & 0x2) {
+ return GetUncachedSymbol(*reinterpret_cast<const void *const *>(address));
+ }
+
+ return nullptr;
+ }
+#else
+ return GetUncachedSymbol(pc);
+#endif
+}
+
bool RemoveAllSymbolDecorators(void) {
if (!g_decorators_mu.TryLock()) {
// Someone else is using decorators. Get out.