mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Support Mach-O on backtrace with DWARF
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65202 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
fe735bd30f
commit
595056135f
4 changed files with 228 additions and 67 deletions
286
addr2line.c
286
addr2line.c
|
@ -28,7 +28,7 @@
|
||||||
#include "missing/stdbool.h"
|
#include "missing/stdbool.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_ELF
|
#if defined(USE_ELF) || defined(HAVE_MACH_O_LOADER_H)
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
@ -41,12 +41,6 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#ifdef __OpenBSD__
|
|
||||||
#include <elf_abi.h>
|
|
||||||
#else
|
|
||||||
#include <elf.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Make alloca work the best possible way. */
|
/* Make alloca work the best possible way. */
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
# ifndef alloca
|
# ifndef alloca
|
||||||
|
@ -70,6 +64,47 @@ void *alloca();
|
||||||
# include <dlfcn.h>
|
# include <dlfcn.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_MACH_O_LOADER_H
|
||||||
|
# include <mach-o/loader.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_ELF
|
||||||
|
# ifdef __OpenBSD__
|
||||||
|
# include <elf_abi.h>
|
||||||
|
# else
|
||||||
|
# include <elf.h>
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#ifndef ElfW
|
||||||
|
# if SIZEOF_VOIDP == 8
|
||||||
|
# define ElfW(x) Elf64##_##x
|
||||||
|
# else
|
||||||
|
# define ElfW(x) Elf32##_##x
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#ifndef ELF_ST_TYPE
|
||||||
|
# if SIZEOF_VOIDP == 8
|
||||||
|
# define ELF_ST_TYPE ELF64_ST_TYPE
|
||||||
|
# else
|
||||||
|
# define ELF_ST_TYPE ELF32_ST_TYPE
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SHF_COMPRESSED
|
||||||
|
# if defined(ELFCOMPRESS_ZLIB) && defined(HAVE_LIBZ)
|
||||||
|
/* FreeBSD 11.0 lacks ELFCOMPRESS_ZLIB */
|
||||||
|
# include <zlib.h>
|
||||||
|
# define SUPPORT_COMPRESSED_DEBUG_LINE
|
||||||
|
# endif
|
||||||
|
#else /* compatibility with glibc < 2.22 */
|
||||||
|
# define SHF_COMPRESSED 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PATH_MAX
|
||||||
|
#define PATH_MAX 4096
|
||||||
|
#endif
|
||||||
|
|
||||||
#define DW_LNS_copy 0x01
|
#define DW_LNS_copy 0x01
|
||||||
#define DW_LNS_advance_pc 0x02
|
#define DW_LNS_advance_pc 0x02
|
||||||
#define DW_LNS_advance_line 0x03
|
#define DW_LNS_advance_line 0x03
|
||||||
|
@ -89,34 +124,6 @@ void *alloca();
|
||||||
#define DW_LNE_define_file 0x03
|
#define DW_LNE_define_file 0x03
|
||||||
#define DW_LNE_set_discriminator 0x04 /* DWARF4 */
|
#define DW_LNE_set_discriminator 0x04 /* DWARF4 */
|
||||||
|
|
||||||
#ifndef ElfW
|
|
||||||
# if SIZEOF_VOIDP == 8
|
|
||||||
# define ElfW(x) Elf64##_##x
|
|
||||||
# else
|
|
||||||
# define ElfW(x) Elf32##_##x
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
#ifndef ELF_ST_TYPE
|
|
||||||
# if SIZEOF_VOIDP == 8
|
|
||||||
# define ELF_ST_TYPE ELF64_ST_TYPE
|
|
||||||
# else
|
|
||||||
# define ELF_ST_TYPE ELF32_ST_TYPE
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
#ifndef PATH_MAX
|
|
||||||
#define PATH_MAX 4096
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SHF_COMPRESSED
|
|
||||||
# if defined(ELFCOMPRESS_ZLIB) && defined(HAVE_LIBZ)
|
|
||||||
/* FreeBSD 11.0 lacks ELFCOMPRESS_ZLIB */
|
|
||||||
# include <zlib.h>
|
|
||||||
# define SUPPORT_COMPRESSED_DEBUG_LINE
|
|
||||||
# endif
|
|
||||||
#else /* compatibility with glibc < 2.22 */
|
|
||||||
# define SHF_COMPRESSED 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PRINTF_ARGS(static int kprintf(const char *fmt, ...), 1, 2);
|
PRINTF_ARGS(static int kprintf(const char *fmt, ...), 1, 2);
|
||||||
|
|
||||||
typedef struct line_info {
|
typedef struct line_info {
|
||||||
|
@ -133,9 +140,9 @@ typedef struct line_info {
|
||||||
} line_info_t;
|
} line_info_t;
|
||||||
|
|
||||||
struct dwarf_section {
|
struct dwarf_section {
|
||||||
ElfW(Shdr) *shdr;
|
|
||||||
char *ptr;
|
char *ptr;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
uint64_t flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct obj_info {
|
typedef struct obj_info {
|
||||||
|
@ -485,6 +492,7 @@ append_obj(obj_info_t **objp)
|
||||||
*objp = newobj;
|
*objp = newobj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_ELF
|
||||||
static void
|
static void
|
||||||
follow_debuglink(const char *debuglink, int num_traces, void **traces,
|
follow_debuglink(const char *debuglink, int num_traces, void **traces,
|
||||||
obj_info_t **objp, line_info_t *lines, int offset)
|
obj_info_t **objp, line_info_t *lines, int offset)
|
||||||
|
@ -518,6 +526,7 @@ follow_debuglink(const char *debuglink, int num_traces, void **traces,
|
||||||
o2->path = o1->path;
|
o2->path = o1->path;
|
||||||
fill_lines(num_traces, traces, 0, objp, lines, offset);
|
fill_lines(num_traces, traces, 0, objp, lines, offset);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -1371,7 +1380,7 @@ ranges_include(DebugInfoReader *reader, ranges_t *ptr, uint64_t addr)
|
||||||
/* base address selection entry */
|
/* base address selection entry */
|
||||||
base = to;
|
base = to;
|
||||||
}
|
}
|
||||||
else if (base + from <= addr && addr <= base + to) {
|
else if (base + from <= addr && addr < base + to) {
|
||||||
return from;
|
return from;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1393,22 +1402,21 @@ ranges_inspect(DebugInfoReader *reader, ranges_t *ptr)
|
||||||
fprintf(stderr,"low_pc_set:%d high_pc_set:%d ranges_set:%d\n",ptr->low_pc_set,ptr->high_pc_set,ptr->ranges_set);
|
fprintf(stderr,"low_pc_set:%d high_pc_set:%d ranges_set:%d\n",ptr->low_pc_set,ptr->high_pc_set,ptr->ranges_set);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
fprintf(stderr,"low_pc:%lx high_pc:%lx\n",ptr->low_pc,ptr->high_pc);
|
fprintf(stderr,"low_pc:%"PRIx64" high_pc:%"PRIx64"\n",ptr->low_pc,ptr->high_pc);
|
||||||
}
|
}
|
||||||
else if (ptr->ranges_set) {
|
else if (ptr->ranges_set) {
|
||||||
char *p;
|
char *p = reader->obj->debug_ranges.ptr + ptr->ranges;
|
||||||
fprintf(stderr,"low_pc:%lx ranges:%lx ",ptr->low_pc,ptr->ranges);
|
fprintf(stderr,"low_pc:%"PRIx64" ranges:%"PRIx64" %lx ",ptr->low_pc,ptr->ranges, p-reader->obj->mapped);
|
||||||
p = reader->obj->debug_ranges.ptr + ptr->ranges;
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
uintptr_t from = read_uintptr(&p);
|
uintptr_t from = read_uintptr(&p);
|
||||||
uintptr_t to = read_uintptr(&p);
|
uintptr_t to = read_uintptr(&p);
|
||||||
if (!from && !to) break;
|
if (!from && !to) break;
|
||||||
fprintf(stderr,"%lx-%lx ",ptr->low_pc+from,ptr->low_pc+to);
|
fprintf(stderr,"%"PRIx64"-%"PRIx64" ",ptr->low_pc+from,ptr->low_pc+to);
|
||||||
}
|
}
|
||||||
fprintf(stderr,"\n");
|
fprintf(stderr,"\n");
|
||||||
}
|
}
|
||||||
else if (ptr->low_pc_set) {
|
else if (ptr->low_pc_set) {
|
||||||
fprintf(stderr,"low_pc:%lx\n",ptr->low_pc);
|
fprintf(stderr,"low_pc:%"PRIx64"\n",ptr->low_pc);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fprintf(stderr,"empty\n");
|
fprintf(stderr,"empty\n");
|
||||||
|
@ -1565,12 +1573,13 @@ debug_info_read(DebugInfoReader *reader, int num_traces, void **traces,
|
||||||
lines[i].path = reader->obj->path;
|
lines[i].path = reader->obj->path;
|
||||||
lines[i].base_addr = line.base_addr;
|
lines[i].base_addr = line.base_addr;
|
||||||
lines[i].sname = line.sname;
|
lines[i].sname = line.sname;
|
||||||
lines[i].saddr = reader->obj->base_addr + saddr;
|
lines[i].saddr = saddr + reader->obj->base_addr - reader->obj->vmaddr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_ELF
|
||||||
static unsigned long
|
static unsigned long
|
||||||
uncompress_debug_section(ElfW(Shdr) *shdr, char *file, char **ptr)
|
uncompress_debug_section(ElfW(Shdr) *shdr, char *file, char **ptr)
|
||||||
{
|
{
|
||||||
|
@ -1605,7 +1614,6 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
char *shstr;
|
char *shstr;
|
||||||
char *section_name;
|
|
||||||
ElfW(Ehdr) *ehdr;
|
ElfW(Ehdr) *ehdr;
|
||||||
ElfW(Shdr) *shdr, *shstr_shdr;
|
ElfW(Shdr) *shdr, *shstr_shdr;
|
||||||
ElfW(Shdr) *gnu_debuglink_shdr = NULL;
|
ElfW(Shdr) *gnu_debuglink_shdr = NULL;
|
||||||
|
@ -1663,7 +1671,7 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
|
||||||
shstr = file + shstr_shdr->sh_offset;
|
shstr = file + shstr_shdr->sh_offset;
|
||||||
|
|
||||||
for (i = 0; i < ehdr->e_shnum; i++) {
|
for (i = 0; i < ehdr->e_shnum; i++) {
|
||||||
section_name = shstr + shdr[i].sh_name;
|
char *section_name = shstr + shdr[i].sh_name;
|
||||||
switch (shdr[i].sh_type) {
|
switch (shdr[i].sh_type) {
|
||||||
case SHT_STRTAB:
|
case SHT_STRTAB:
|
||||||
if (!strcmp(section_name, ".strtab")) {
|
if (!strcmp(section_name, ".strtab")) {
|
||||||
|
@ -1693,11 +1701,21 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
|
||||||
".debug_ranges",
|
".debug_ranges",
|
||||||
".debug_str"
|
".debug_str"
|
||||||
};
|
};
|
||||||
|
|
||||||
for (j=0; j < DWARF_SECTION_COUNT; j++) {
|
for (j=0; j < DWARF_SECTION_COUNT; j++) {
|
||||||
if (strcmp(section_name, debug_section_names[j]) == 0) {
|
struct dwarf_section *s = obj_dwarf_section_at(obj, j);
|
||||||
obj_dwarf_section_at(obj, j)->shdr = &shdr[i];
|
|
||||||
break;
|
if (strcmp(section_name, debug_section_names[j]) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
s->ptr = file + shdr[i].sh_offset;
|
||||||
|
s->size = shdr[i].sh_size;
|
||||||
|
s->flags = shdr[i].sh_flags;
|
||||||
|
if (s->flags & SHF_COMPRESSED) {
|
||||||
|
s->size = uncompress_debug_section(&shdr[i], file, &s->ptr);
|
||||||
|
if (!s->size) goto fail;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1720,6 +1738,7 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
|
||||||
if (ELF_ST_TYPE(sym->st_info) != STT_FUNC || sym->st_size == 0) continue;
|
if (ELF_ST_TYPE(sym->st_info) != STT_FUNC || sym->st_size == 0) continue;
|
||||||
s = dlsym(handle, strtab + sym->st_name);
|
s = dlsym(handle, strtab + sym->st_name);
|
||||||
if (s && dladdr(s, &info)) {
|
if (s && dladdr(s, &info)) {
|
||||||
|
obj->base_addr = dladdr_fbase;
|
||||||
dladdr_fbase = (uintptr_t)info.dli_fbase;
|
dladdr_fbase = (uintptr_t)info.dli_fbase;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1736,21 +1755,6 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obj->debug_info.shdr) {
|
|
||||||
size_t j;
|
|
||||||
for (j=0; j < DWARF_SECTION_COUNT; j++) {
|
|
||||||
struct dwarf_section *s = obj_dwarf_section_at(obj, j);
|
|
||||||
ElfW(Shdr) *shdr = s->shdr;
|
|
||||||
if (!shdr) break;
|
|
||||||
s->ptr = file + shdr->sh_offset;
|
|
||||||
s->size = shdr->sh_size;
|
|
||||||
if (shdr->sh_flags & SHF_COMPRESSED) {
|
|
||||||
s->size = uncompress_debug_section(shdr, file, &s->ptr);
|
|
||||||
if (!s->size) goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obj->debug_info.ptr && obj->debug_abbrev.ptr) {
|
if (obj->debug_info.ptr && obj->debug_abbrev.ptr) {
|
||||||
DebugInfoReader reader;
|
DebugInfoReader reader;
|
||||||
debug_info_reader_init(&reader, obj);
|
debug_info_reader_init(&reader, obj);
|
||||||
|
@ -1813,6 +1817,158 @@ finish:
|
||||||
fail:
|
fail:
|
||||||
return (uintptr_t)-1;
|
return (uintptr_t)-1;
|
||||||
}
|
}
|
||||||
|
#else /* Mach-O */
|
||||||
|
/* read file and fill lines */
|
||||||
|
static uintptr_t
|
||||||
|
fill_lines(int num_traces, void **traces, int check_debuglink,
|
||||||
|
obj_info_t **objp, line_info_t *lines, int offset)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
off_t filesize;
|
||||||
|
char *file, *p;
|
||||||
|
obj_info_t *obj = *objp;
|
||||||
|
struct mach_header_64 *header;
|
||||||
|
uintptr_t dladdr_fbase = 0;
|
||||||
|
|
||||||
|
{
|
||||||
|
char *s = binary_filename;
|
||||||
|
char *base = strrchr(binary_filename, '/')+1;
|
||||||
|
size_t max = PATH_MAX;
|
||||||
|
size_t size = strlen(binary_filename);
|
||||||
|
size_t basesize = size - (base - binary_filename);
|
||||||
|
s += size;
|
||||||
|
max -= size;
|
||||||
|
size = strlcpy(s, ".dSYM/Contents/Resources/DWARF/", max);
|
||||||
|
if (size == 0) goto fail;
|
||||||
|
s += size;
|
||||||
|
max -= size;
|
||||||
|
if (max <= basesize) goto fail;
|
||||||
|
memcpy(s, base, basesize);
|
||||||
|
s[basesize] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = open(binary_filename, O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
filesize = lseek(fd, 0, SEEK_END);
|
||||||
|
if (filesize < 0) {
|
||||||
|
int e = errno;
|
||||||
|
close(fd);
|
||||||
|
kprintf("lseek: %s\n", strerror(e));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#if SIZEOF_OFF_T > SIZEOF_SIZE_T
|
||||||
|
if (filesize > (off_t)SIZE_MAX) {
|
||||||
|
close(fd);
|
||||||
|
kprintf("Too large file %s\n", binary_filename);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
lseek(fd, 0, SEEK_SET);
|
||||||
|
/* async-signal unsafe */
|
||||||
|
file = (char *)mmap(NULL, (size_t)filesize, PROT_READ, MAP_SHARED, fd, 0);
|
||||||
|
if (file == MAP_FAILED) {
|
||||||
|
int e = errno;
|
||||||
|
close(fd);
|
||||||
|
kprintf("mmap: %s\n", strerror(e));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
obj->mapped = file;
|
||||||
|
obj->mapped_size = (size_t)filesize;
|
||||||
|
|
||||||
|
header = (struct mach_header_64 *)file;
|
||||||
|
if (header->magic != MH_MAGIC_64) {
|
||||||
|
/* TODO: universal binaries */
|
||||||
|
kprintf("'%s' is not a 64-bit Mach-O file!\n",binary_filename);
|
||||||
|
close(fd);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = file + sizeof(struct mach_header_64);
|
||||||
|
for (uint32_t i = 0; i < (uint32_t)header->ncmds; i++) {
|
||||||
|
struct load_command *lcmd = (struct load_command *)p;
|
||||||
|
switch (lcmd->cmd) {
|
||||||
|
case LC_SEGMENT_64:
|
||||||
|
{
|
||||||
|
static const char *debug_section_names[] = {
|
||||||
|
"__debug_abbrev",
|
||||||
|
"__debug_info",
|
||||||
|
"__debug_line",
|
||||||
|
"__debug_ranges",
|
||||||
|
"__debug_str"
|
||||||
|
};
|
||||||
|
struct segment_command_64 *scmd = (struct segment_command_64 *)lcmd;
|
||||||
|
if (strcmp(scmd->segname, "__TEXT") == 0) {
|
||||||
|
obj->vmaddr = scmd->vmaddr;
|
||||||
|
}
|
||||||
|
else if (strcmp(scmd->segname, "__DWARF") == 0) {
|
||||||
|
p += sizeof(struct segment_command_64);
|
||||||
|
for (uint64_t i = 0; i < scmd->nsects; i++) {
|
||||||
|
struct section_64 *sect = (struct section_64 *)p;
|
||||||
|
p += sizeof(struct section_64);
|
||||||
|
for (int j=0; j < DWARF_SECTION_COUNT; j++) {
|
||||||
|
struct dwarf_section *s = obj_dwarf_section_at(obj, j);
|
||||||
|
|
||||||
|
if (strcmp(sect->sectname, debug_section_names[j]) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
s->ptr = file + sect->offset;
|
||||||
|
s->size = sect->size;
|
||||||
|
s->flags = sect->flags;
|
||||||
|
if (s->flags & SHF_COMPRESSED) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
case LC_SYMTAB:
|
||||||
|
{
|
||||||
|
struct symtab_command *c = (struct symtab_command *)lcmd;
|
||||||
|
struct nlist_64 *nl = (struct nlist *)(file + c->symoff);
|
||||||
|
char *strtab = file + c->stroff;
|
||||||
|
uint32_t j;
|
||||||
|
kprintf("[%2d]: %x/symtab %lx\n", i, c->cmd, p);
|
||||||
|
for (j = 0; j < c->nsyms; j++) {
|
||||||
|
struct nlist_64 *e = &nl[j];
|
||||||
|
if (!(e->n_type & N_STAB)) continue;
|
||||||
|
/* if (e->n_type != N_FUN) continue; */
|
||||||
|
kprintf("[%2d][%4d]: %02x/%x/%x: %s %lx\n", i, j,
|
||||||
|
e->n_type,e->n_sect,e->n_desc,strtab+e->n_un.n_strx,e->n_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
p += lcmd->cmdsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj->debug_info.ptr && obj->debug_abbrev.ptr) {
|
||||||
|
DebugInfoReader reader;
|
||||||
|
debug_info_reader_init(&reader, obj);
|
||||||
|
while (reader.p < reader.pend) {
|
||||||
|
di_read_cu(&reader);
|
||||||
|
debug_info_read(&reader, num_traces, traces, lines, offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parse_debug_line(num_traces, traces,
|
||||||
|
obj->debug_line.ptr,
|
||||||
|
obj->debug_line.size,
|
||||||
|
obj, lines, offset) == -1)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
return dladdr_fbase;
|
||||||
|
fail:
|
||||||
|
return (uintptr_t)-1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#define HAVE_MAIN_EXE_PATH
|
#define HAVE_MAIN_EXE_PATH
|
||||||
#if defined(__FreeBSD__)
|
#if defined(__FreeBSD__)
|
||||||
|
@ -1971,7 +2127,7 @@ next_line:
|
||||||
obj_info_t *o = obj;
|
obj_info_t *o = obj;
|
||||||
for (i=0; i < DWARF_SECTION_COUNT; i++) {
|
for (i=0; i < DWARF_SECTION_COUNT; i++) {
|
||||||
struct dwarf_section *s = obj_dwarf_section_at(obj, i);
|
struct dwarf_section *s = obj_dwarf_section_at(obj, i);
|
||||||
if (s->shdr && (s->shdr->sh_flags & SHF_COMPRESSED)) {
|
if (s->flags & SHF_COMPRESSED) {
|
||||||
free(s->ptr);
|
free(s->ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#ifndef RUBY_ADDR2LINE_H
|
#ifndef RUBY_ADDR2LINE_H
|
||||||
#define RUBY_ADDR2LINE_H
|
#define RUBY_ADDR2LINE_H
|
||||||
|
|
||||||
#ifdef USE_ELF
|
#if (defined(USE_ELF) || defined(HAVE_MACH_O_LOADER_H))
|
||||||
|
|
||||||
void
|
void
|
||||||
rb_dump_backtrace_with_lines(int num_traces, void **traces);
|
rb_dump_backtrace_with_lines(int num_traces, void **traces);
|
||||||
|
|
|
@ -2515,6 +2515,11 @@ AS_IF([test "$rb_cv_binary_elf" = yes], [
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
|
|
||||||
|
AC_CHECK_HEADERS([mach-o/loader.h])
|
||||||
|
AS_IF([test "$ac_cv_header_mach_o_loader_h" = yes], [
|
||||||
|
AC_LIBOBJ([addr2line])
|
||||||
|
])
|
||||||
|
|
||||||
AS_CASE(["$target_os"],
|
AS_CASE(["$target_os"],
|
||||||
[linux* | gnu* | k*bsd*-gnu | bsdi* | kopensolaris*-gnu], [
|
[linux* | gnu* | k*bsd*-gnu | bsdi* | kopensolaris*-gnu], [
|
||||||
AS_IF([test "$rb_cv_binary_elf" = no], [
|
AS_IF([test "$rb_cv_binary_elf" = no], [
|
||||||
|
|
|
@ -713,7 +713,7 @@ rb_print_backtrace(void)
|
||||||
#define MAX_NATIVE_TRACE 1024
|
#define MAX_NATIVE_TRACE 1024
|
||||||
static void *trace[MAX_NATIVE_TRACE];
|
static void *trace[MAX_NATIVE_TRACE];
|
||||||
int n = (int)backtrace(trace, MAX_NATIVE_TRACE);
|
int n = (int)backtrace(trace, MAX_NATIVE_TRACE);
|
||||||
#if defined(USE_ELF) && defined(HAVE_DLADDR) && !defined(__sparc)
|
#if (defined(USE_ELF) || defined(HAVE_MACH_O_LOADER_H)) && defined(HAVE_DLADDR) && !defined(__sparc)
|
||||||
rb_dump_backtrace_with_lines(n, trace);
|
rb_dump_backtrace_with_lines(n, trace);
|
||||||
#else
|
#else
|
||||||
char **syms = backtrace_symbols(trace, n);
|
char **syms = backtrace_symbols(trace, n);
|
||||||
|
|
Loading…
Add table
Reference in a new issue