remove unused files
[platform/upstream/gcc48.git] / libsanitizer / tsan / tsan_symbolize_addr2line_linux.cc
1 //===-- tsan_symbolize_addr2line.cc ---------------------------------------===//
2 //
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file is a part of ThreadSanitizer (TSan), a race detector.
9 //
10 //===----------------------------------------------------------------------===//
11 #include "sanitizer_common/sanitizer_common.h"
12 #include "sanitizer_common/sanitizer_libc.h"
13 #include "tsan_symbolize.h"
14 #include "tsan_mman.h"
15 #include "tsan_rtl.h"
16 #include "tsan_platform.h"
17
18 #include <unistd.h>
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <errno.h>
22 #include <link.h>
23 #include <linux/limits.h>
24 #include <sys/types.h>
25
26 namespace __tsan {
27
28 struct ModuleDesc {
29   const char *fullname;
30   const char *name;
31   uptr base;
32   int inp_fd;
33   int out_fd;
34 };
35
36 struct SectionDesc {
37   SectionDesc *next;
38   ModuleDesc *module;
39   uptr base;
40   uptr end;
41 };
42
43 struct DlIteratePhdrCtx {
44   SectionDesc *sections;
45   bool is_first;
46 };
47
48 static void NOINLINE InitModule(ModuleDesc *m) {
49   int outfd[2] = {};
50   if (pipe(&outfd[0])) {
51     Printf("ThreadSanitizer: outfd pipe() failed (%d)\n", errno);
52     Die();
53   }
54   int infd[2] = {};
55   if (pipe(&infd[0])) {
56     Printf("ThreadSanitizer: infd pipe() failed (%d)\n", errno);
57     Die();
58   }
59   int pid = fork();
60   if (pid == 0) {
61     __sanitizer_set_report_fd(STDERR_FILENO);
62     internal_close(STDOUT_FILENO);
63     internal_close(STDIN_FILENO);
64     internal_dup2(outfd[0], STDIN_FILENO);
65     internal_dup2(infd[1], STDOUT_FILENO);
66     internal_close(outfd[0]);
67     internal_close(outfd[1]);
68     internal_close(infd[0]);
69     internal_close(infd[1]);
70     for (int fd = getdtablesize(); fd > 2; fd--)
71       internal_close(fd);
72     execl("/usr/bin/addr2line", "/usr/bin/addr2line", "-Cfe", m->fullname, 0);
73     _exit(0);
74   } else if (pid < 0) {
75     Printf("ThreadSanitizer: failed to fork symbolizer\n");
76     Die();
77   }
78   internal_close(outfd[0]);
79   internal_close(infd[1]);
80   m->inp_fd = infd[0];
81   m->out_fd = outfd[1];
82 }
83
84 static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) {
85   DlIteratePhdrCtx *ctx = (DlIteratePhdrCtx*)arg;
86   InternalScopedBuffer<char> tmp(128);
87   if (ctx->is_first) {
88     internal_snprintf(tmp.data(), tmp.size(), "/proc/%d/exe", GetPid());
89     info->dlpi_name = tmp.data();
90   }
91   ctx->is_first = false;
92   if (info->dlpi_name == 0 || info->dlpi_name[0] == 0)
93     return 0;
94   ModuleDesc *m = (ModuleDesc*)internal_alloc(MBlockReportStack,
95                                               sizeof(ModuleDesc));
96   m->fullname = internal_strdup(info->dlpi_name);
97   m->name = internal_strrchr(m->fullname, '/');
98   if (m->name)
99     m->name += 1;
100   else
101     m->name = m->fullname;
102   m->base = (uptr)info->dlpi_addr;
103   m->inp_fd = -1;
104   m->out_fd = -1;
105   DPrintf2("Module %s %zx\n", m->name, m->base);
106   for (int i = 0; i < info->dlpi_phnum; i++) {
107     const Elf64_Phdr *s = &info->dlpi_phdr[i];
108     DPrintf2("  Section p_type=%zx p_offset=%zx p_vaddr=%zx p_paddr=%zx"
109         " p_filesz=%zx p_memsz=%zx p_flags=%zx p_align=%zx\n",
110             (uptr)s->p_type, (uptr)s->p_offset, (uptr)s->p_vaddr,
111             (uptr)s->p_paddr, (uptr)s->p_filesz, (uptr)s->p_memsz,
112             (uptr)s->p_flags, (uptr)s->p_align);
113     if (s->p_type != PT_LOAD)
114       continue;
115     SectionDesc *sec = (SectionDesc*)internal_alloc(MBlockReportStack,
116                                                     sizeof(SectionDesc));
117     sec->module = m;
118     sec->base = info->dlpi_addr + s->p_vaddr;
119     sec->end = sec->base + s->p_memsz;
120     sec->next = ctx->sections;
121     ctx->sections = sec;
122     DPrintf2("  Section %zx-%zx\n", sec->base, sec->end);
123   }
124   return 0;
125 }
126
127 static SectionDesc *InitSections() {
128   DlIteratePhdrCtx ctx = {0, true};
129   dl_iterate_phdr(dl_iterate_phdr_cb, &ctx);
130   return ctx.sections;
131 }
132
133 static SectionDesc *GetSectionDesc(uptr addr) {
134   static SectionDesc *sections = 0;
135   if (sections == 0)
136     sections = InitSections();
137   for (SectionDesc *s = sections; s; s = s->next) {
138     if (addr >= s->base && addr < s->end) {
139       if (s->module->inp_fd == -1)
140         InitModule(s->module);
141       return s;
142     }
143   }
144   return 0;
145 }
146
147 ReportStack *SymbolizeCodeAddr2Line(uptr addr) {
148   SectionDesc *s = GetSectionDesc(addr);
149   if (s == 0)
150     return NewReportStackEntry(addr);
151   ModuleDesc *m = s->module;
152   uptr offset = addr - m->base;
153   char addrstr[32];
154   internal_snprintf(addrstr, sizeof(addrstr), "%p\n", (void*)offset);
155   if (0 >= internal_write(m->out_fd, addrstr, internal_strlen(addrstr))) {
156     Printf("ThreadSanitizer: can't write from symbolizer (%d, %d)\n",
157         m->out_fd, errno);
158     Die();
159   }
160   InternalScopedBuffer<char> func(1024);
161   ssize_t len = internal_read(m->inp_fd, func.data(), func.size() - 1);
162   if (len <= 0) {
163     Printf("ThreadSanitizer: can't read from symbolizer (%d, %d)\n",
164         m->inp_fd, errno);
165     Die();
166   }
167   func.data()[len] = 0;
168   ReportStack *res = NewReportStackEntry(addr);
169   res->module = internal_strdup(m->name);
170   res->offset = offset;
171   char *pos = (char*)internal_strchr(func.data(), '\n');
172   if (pos && func[0] != '?') {
173     res->func = (char*)internal_alloc(MBlockReportStack, pos - func.data() + 1);
174     internal_memcpy(res->func, func.data(), pos - func.data());
175     res->func[pos - func.data()] = 0;
176     char *pos2 = (char*)internal_strchr(pos, ':');
177     if (pos2) {
178       res->file = (char*)internal_alloc(MBlockReportStack, pos2 - pos - 1 + 1);
179       internal_memcpy(res->file, pos + 1, pos2 - pos - 1);
180       res->file[pos2 - pos - 1] = 0;
181       res->line = atoi(pos2 + 1);
182      }
183   }
184   return res;
185 }
186
187 ReportStack *SymbolizeDataAddr2Line(uptr addr) {
188   return 0;
189 }
190
191 }  // namespace __tsan