blob: 1f3d0a885bb19e18f66a9e3b534539d9203dfae5 [file] [log] [blame]
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +00001/*
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +00002 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +00003 * honggfuzz - architecture dependent code (LINUX/BFD)
4 * -----------------------------------------
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +00005 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +00006 * Author: Robert Swiecki <swiecki@google.com>
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +00007 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +00008 * Copyright 2010-2015 by Google Inc. All Rights Reserved.
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +00009 *
10 * Licensed under the Apache License, Version 2.0 (the "License"); you may
11 * not use this file except in compliance with the License. You may obtain
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000012 * a copy of the License at
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +000013 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000014 * http://www.apache.org/licenses/LICENSE-2.0
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +000015 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000016 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
19 * implied. See the License for the specific language governing
20 * permissions and limitations under the License.
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +000021 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000022 */
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +000023
24#include "common.h"
25#include "linux/bfd.h"
26
27#include <bfd.h>
robert.swiecki@gmail.com9e2d43d2015-02-16 12:17:39 +000028#include <dis-asm.h>
29#include <stdarg.h>
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +000030#include <stddef.h>
31#include <stdio.h>
32#include <stdint.h>
33#include <stdlib.h>
robert.swiecki@gmail.com9e2d43d2015-02-16 12:17:39 +000034#include <string.h>
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +000035#include <inttypes.h>
36#include <unistd.h>
37
38#include "files.h"
39#include "log.h"
40#include "util.h"
41
robert.swiecki@gmail.com576232b2015-02-14 19:44:32 +000042typedef struct {
43 bfd *bfdh;
44 asection *section;
45 asymbol **syms;
46} bfd_t;
47
robert.swiecki@gmail.comb45bbc32015-02-16 15:11:50 +000048void arch_bfdPrepare(void)
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +000049{
50 bfd_init();
robert.swiecki@gmail.comb45bbc32015-02-16 15:11:50 +000051}
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +000052
robert.swiecki@gmail.comb45bbc32015-02-16 15:11:50 +000053static bool arch_bfdInit(pid_t pid, bfd_t * bfdParams)
54{
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +000055 char fname[PATH_MAX];
56 snprintf(fname, sizeof(fname), "/proc/%d/exe", pid);
robert.swiecki@gmail.com576232b2015-02-14 19:44:32 +000057 if ((bfdParams->bfdh = bfd_openr(fname, 0)) == NULL) {
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +000058 LOGMSG(l_ERROR, "bfd_openr(%s) failed", fname);
59 return false;
60 }
61
robert.swiecki@gmail.com576232b2015-02-14 19:44:32 +000062 if (!bfd_check_format(bfdParams->bfdh, bfd_object)) {
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +000063 LOGMSG(l_ERROR, "bfd_check_format() failed");
64 return false;
65 }
66
robert.swiecki@gmail.com576232b2015-02-14 19:44:32 +000067 int storage_needed = bfd_get_symtab_upper_bound(bfdParams->bfdh);
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +000068 if (storage_needed <= 0) {
69 LOGMSG(l_ERROR, "bfd_get_symtab_upper_bound() returned '%d'", storage_needed);
70 return false;
71 }
72
robert.swiecki@gmail.com576232b2015-02-14 19:44:32 +000073 if ((bfdParams->syms = (asymbol **) malloc(storage_needed)) == NULL) {
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +000074 LOGMSG_P(l_ERROR, "malloc(%d) failed", storage_needed);
75 return false;
76 }
robert.swiecki@gmail.com576232b2015-02-14 19:44:32 +000077 bfd_canonicalize_symtab(bfdParams->bfdh, bfdParams->syms);
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +000078
robert.swiecki@gmail.com576232b2015-02-14 19:44:32 +000079 if ((bfdParams->section = bfd_get_section_by_name(bfdParams->bfdh, ".text")) == NULL) {
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +000080 LOGMSG(l_ERROR, "bfd_get_section_by_name('.text') failed");
81 return false;
82 }
83
84 return true;
85}
86
robert.swiecki@gmail.com576232b2015-02-14 19:44:32 +000087static void arch_bfdDestroy(bfd_t * bfdParams)
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +000088{
robert.swiecki@gmail.com576232b2015-02-14 19:44:32 +000089 if (bfdParams->syms) {
90 free(bfdParams->syms);
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +000091 }
robert.swiecki@gmail.come87be972015-02-16 13:44:43 +000092 if (bfdParams->bfdh) {
93 bfd_close(bfdParams->bfdh);
94 }
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +000095 return;
96}
97
98void arch_bfdResolveSyms(pid_t pid, funcs_t * funcs, size_t num)
99{
robert.swiecki@gmail.com576232b2015-02-14 19:44:32 +0000100 bfd_t bfdParams = {
101 .bfdh = NULL,
102 .section = NULL,
103 .syms = NULL,
104 };
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +0000105
robert.swiecki@gmail.com576232b2015-02-14 19:44:32 +0000106 if (arch_bfdInit(pid, &bfdParams) == false) {
107 arch_bfdDestroy(&bfdParams);
108 return;
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +0000109 }
110
111 const char *func;
112 const char *file;
113 unsigned int line;
114 for (unsigned int i = 0; i < num; i++) {
115 snprintf(funcs[i].func, sizeof(funcs->func), "[UNKNOWN]");
116 if (funcs[i].pc == NULL) {
117 continue;
118 }
robert.swiecki@gmail.com576232b2015-02-14 19:44:32 +0000119 long offset = (long)funcs[i].pc - bfdParams.section->vma;
120 if ((offset < 0 || (unsigned long)offset > bfdParams.section->size)) {
robert.swiecki@gmail.com5be88822015-02-14 13:12:09 +0000121 continue;
122 }
robert.swiecki@gmail.com576232b2015-02-14 19:44:32 +0000123 if (bfd_find_nearest_line
124 (bfdParams.bfdh, bfdParams.section, bfdParams.syms, offset, &file, &func, &line)) {
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +0000125 snprintf(funcs[i].func, sizeof(funcs->func), "%s", func);
robert.swiecki@gmail.com90e99112015-02-15 02:05:14 +0000126 funcs[i].line = line;
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +0000127 }
128 }
129
robert.swiecki@gmail.com576232b2015-02-14 19:44:32 +0000130 arch_bfdDestroy(&bfdParams);
131 return;
robert.swiecki@gmail.coma0d87142015-02-14 13:11:18 +0000132}
robert.swiecki@gmail.com9e2d43d2015-02-16 12:17:39 +0000133
134static int arch_bfdFPrintF(void *buf, const char *fmt, ...)
135{
136 va_list args;
137 va_start(args, fmt);
138 int ret = util_vssnprintf(buf, _HF_INSTR_SZ, fmt, args);
139 va_end(args);
140
141 return ret;
142}
143
144void arch_bfdDisasm(pid_t pid, uint8_t * mem, size_t size, char *instr)
145{
robert.swiecki@gmail.com9e2d43d2015-02-16 12:17:39 +0000146 char fname[PATH_MAX];
147 snprintf(fname, sizeof(fname), "/proc/%d/exe", pid);
148 bfd *bfdh = bfd_openr(fname, NULL);
149 if (bfdh == NULL) {
150 LOGMSG(l_WARN, "bfd_openr('/proc/%d/exe') failed", pid);
robert.swiecki@gmail.comd7123702015-02-16 14:50:50 +0000151 goto out;
robert.swiecki@gmail.com9e2d43d2015-02-16 12:17:39 +0000152 }
153
154 if (!bfd_check_format(bfdh, bfd_object)) {
155 LOGMSG(l_WARN, "bfd_check_format() failed");
robert.swiecki@gmail.comd7123702015-02-16 14:50:50 +0000156 goto out;
robert.swiecki@gmail.com9e2d43d2015-02-16 12:17:39 +0000157 }
158
159 disassembler_ftype disassemble = disassembler(bfdh);
160 if (disassemble == NULL) {
161 LOGMSG(l_WARN, "disassembler() failed");
robert.swiecki@gmail.comd7123702015-02-16 14:50:50 +0000162 goto out;
robert.swiecki@gmail.com9e2d43d2015-02-16 12:17:39 +0000163 }
164
165 struct disassemble_info info;
166 init_disassemble_info(&info, instr, arch_bfdFPrintF);
167 info.arch = bfd_get_arch(bfdh);
168 info.mach = bfd_get_mach(bfdh);
169 info.buffer = mem;
170 info.buffer_length = size;
171 info.section = NULL;
172 disassemble_init_for_target(&info);
173
174 strcpy(instr, "");
175 if (disassemble(0, &info) <= 0) {
176 snprintf(instr, _HF_INSTR_SZ, "[UNKNOWN]");
177 }
robert.swiecki@gmail.comd7123702015-02-16 14:50:50 +0000178
179 out:
180 bfdh ? bfd_close(bfdh) : 0;
robert.swiecki@gmail.com9e2d43d2015-02-16 12:17:39 +0000181 return;
182}