aboutsummaryrefslogtreecommitdiffstats
path: root/addr2line.c
diff options
context:
space:
mode:
authornaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-11-20 22:40:20 +0000
committernaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-11-20 22:40:20 +0000
commit529adb68727c591204d9d41aab513ba06f12f776 (patch)
treeb63e905e7e2d574344b5ba31466de601561bd9fb /addr2line.c
parent26adef94fab56f622cec615ba4cc58ba40a587b7 (diff)
downloadruby-529adb68727c591204d9d41aab513ba06f12f776.tar.gz
Support Universal Binary for macOS
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65896 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'addr2line.c')
-rw-r--r--addr2line.c44
1 files changed, 39 insertions, 5 deletions
diff --git a/addr2line.c b/addr2line.c
index 60b5f253f8..f27efe487c 100644
--- a/addr2line.c
+++ b/addr2line.c
@@ -66,6 +66,8 @@ void *alloca();
#endif
#ifdef HAVE_MACH_O_LOADER_H
+# include <mach-o/fat.h>
+# include <mach-o/ldsyms.h>
# include <mach-o/loader.h>
# include <mach-o/nlist.h>
# include <mach-o/stab.h>
@@ -1829,7 +1831,7 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
# endif
int fd;
off_t filesize;
- char *file, *p;
+ char *file, *p = NULL;
obj_info_t *obj = *objp;
struct LP(mach_header) *header;
uintptr_t dladdr_fbase = 0;
@@ -1890,8 +1892,38 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
obj->mapped_size = (size_t)filesize;
header = (struct LP(mach_header) *)file;
- if (header->magic != LP(MH_MAGIC)) {
- /* TODO: universal binaries */
+ if (header->magic == LP(MH_MAGIC)) {
+ /* non universal binary */
+ p = file;
+ }
+ else if (header->magic == FAT_CIGAM) {
+ struct fat_header *fat = (struct fat_header *)file;
+ char *q = file + sizeof(*fat);
+ uint32_t nfat_arch = __builtin_bswap32(fat->nfat_arch);
+ /* fprintf(stderr,"%d: fat:%s %d\n",__LINE__, binary_filename,nfat_arch); */
+ for (uint32_t i = 0; i < nfat_arch; i++) {
+ struct fat_arch *arch = (struct fat_arch *)q;
+ cpu_type_t cputype = __builtin_bswap32(arch->cputype);
+ cpu_subtype_t cpusubtype = __builtin_bswap32(arch->cpusubtype);
+ uint32_t offset = __builtin_bswap32(arch->offset);
+ /* fprintf(stderr,"%d: fat %d %x/%x %x/%x\n",__LINE__, i, _mh_execute_header.cputype,_mh_execute_header.cpusubtype, cputype,cpusubtype); */
+ if (_mh_execute_header.cputype == cputype &&
+ (_mh_execute_header.cpusubtype & ~CPU_SUBTYPE_MASK) == cpusubtype) {
+ p = file + offset;
+ file = p;
+ header = (struct LP(mach_header) *)p;
+ if (header->magic == LP(MH_MAGIC)) {
+ goto found_mach_header;
+ }
+ break;
+ }
+ q += sizeof(*arch);
+ }
+ kprintf("'%s' is not a Mach-O universal binary file!\n",binary_filename);
+ close(fd);
+ goto fail;
+ }
+ else {
kprintf("'%s' is not a "
# ifdef __LP64__
"64"
@@ -1902,8 +1934,9 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
close(fd);
goto fail;
}
+found_mach_header:
+ p += sizeof(*header);
- p = file + sizeof(*header);
for (uint32_t i = 0; i < (uint32_t)header->ncmds; i++) {
struct load_command *lcmd = (struct load_command *)p;
switch (lcmd->cmd) {
@@ -1955,13 +1988,14 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
for (j = 0; j < cmd->nsyms; j++) {
uintptr_t symsize, d;
struct LP(nlist) *e = &nl[j];
+ /* kprintf("[%2d][%4d]: %02x/%x/%x: %s %llx\n", i, j, e->n_type,e->n_sect,e->n_desc,strtab+e->n_un.n_strx,e->n_value); */
if (e->n_type != N_FUN) continue;
if (e->n_sect) {
saddr = (uintptr_t)e->n_value + obj->base_addr - obj->vmaddr;
sname = strtab + e->n_un.n_strx;
+ /* kprintf("[%2d][%4d]: %02x/%x/%x: %s %llx\n", i, j, e->n_type,e->n_sect,e->n_desc,strtab+e->n_un.n_strx,e->n_value); */
continue;
}
- /* kprintf("[%2d][%4d]: %02x/%x/%x: %s %llx\n", i, j, e->n_type,e->n_sect,e->n_desc,strtab+e->n_un.n_strx,e->n_value); */
for (int k = offset; k < num_traces; k++) {
d = (uintptr_t)traces[k] - saddr;
symsize = e->n_value;