"Fossies" - the Fresh Open Source Software Archive

Member "honggfuzz-2.2/linux/bfd.c" (23 Apr 2020, 7534 Bytes) of package /linux/privat/honggfuzz-2.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "bfd.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.1_vs_2.2.

    1 /*
    2  *
    3  * honggfuzz - architecture dependent code (LINUX/BFD)
    4  * -----------------------------------------
    5  *
    6  * Author: Robert Swiecki <swiecki@google.com>
    7  *
    8  * Copyright 2010-2018 by Google Inc. All Rights Reserved.
    9  *
   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
   12  * a copy of the License at
   13  *
   14  * http://www.apache.org/licenses/LICENSE-2.0
   15  *
   16  * 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.
   21  *
   22  */
   23 
   24 #if !defined(_HF_LINUX_NO_BFD)
   25 
   26 #include "linux/bfd.h"
   27 
   28 #include <bfd.h>
   29 #include <dis-asm.h>
   30 #include <inttypes.h>
   31 #include <pthread.h>
   32 #include <stdarg.h>
   33 #include <stddef.h>
   34 #include <stdint.h>
   35 #include <stdio.h>
   36 #include <stdlib.h>
   37 #include <unistd.h>
   38 
   39 #include "honggfuzz.h"
   40 #include "libhfcommon/common.h"
   41 #include "libhfcommon/files.h"
   42 #include "libhfcommon/log.h"
   43 #include "libhfcommon/util.h"
   44 
   45 #if !defined(bfd_get_section_size)
   46 #define bfd_get_section_size(section) bfd_section_size(section)
   47 #endif /* !defined(bfd_get_section_size) */
   48 #if !defined(bfd_get_section_vma)
   49 #define bfd_get_section_vma(ptr, section) bfd_section_vma(section)
   50 #endif /* !defined(bfd_get_section_size) */
   51 
   52 typedef struct {
   53     bfd* bfdh;
   54     asymbol** syms;
   55     asymbol** dsyms;
   56 } bfd_t;
   57 
   58 /*
   59  * This is probably the only define which was added with binutils 2.29, so we us
   60  * it, do decide which disassembler() prototype from dis-asm.h to use
   61  */
   62 #if defined(FOR_EACH_DISASSEMBLER_OPTION)
   63 #define _HF_BFD_GE_2_29
   64 #endif
   65 
   66 static pthread_mutex_t arch_bfd_mutex = PTHREAD_MUTEX_INITIALIZER;
   67 
   68 static bool arch_bfdInit(pid_t pid, bfd_t* bfdParams) {
   69     char fname[PATH_MAX];
   70     snprintf(fname, sizeof(fname), "/proc/%d/exe", pid);
   71     if ((bfdParams->bfdh = bfd_openr(fname, 0)) == NULL) {
   72         LOG_E("bfd_openr(%s) failed", fname);
   73         return false;
   74     }
   75 
   76     if (!bfd_check_format(bfdParams->bfdh, bfd_object)) {
   77         LOG_E("bfd_check_format() failed");
   78         return false;
   79     }
   80 
   81     int storage_needed = bfd_get_symtab_upper_bound(bfdParams->bfdh);
   82     if (storage_needed <= 0) {
   83         LOG_E("bfd_get_symtab_upper_bound() returned '%d'", storage_needed);
   84         return false;
   85     }
   86     bfdParams->syms = (asymbol**)util_Calloc(storage_needed);
   87     bfd_canonicalize_symtab(bfdParams->bfdh, bfdParams->syms);
   88 
   89     storage_needed = bfd_get_dynamic_symtab_upper_bound(bfdParams->bfdh);
   90     if (storage_needed <= 0) {
   91         LOG_E("bfd_get_dynamic_symtab_upper_bound() returned '%d'", storage_needed);
   92         return false;
   93     }
   94     bfdParams->dsyms = (asymbol**)util_Calloc(storage_needed);
   95     bfd_canonicalize_dynamic_symtab(bfdParams->bfdh, bfdParams->dsyms);
   96 
   97     return true;
   98 }
   99 
  100 static void arch_bfdDestroy(bfd_t* bfdParams) {
  101     if (bfdParams->syms) {
  102         free(bfdParams->syms);
  103         bfdParams->syms = NULL;
  104     }
  105     if (bfdParams->dsyms) {
  106         free(bfdParams->dsyms);
  107         bfdParams->dsyms = NULL;
  108     }
  109     if (bfdParams->bfdh) {
  110         bfd_close(bfdParams->bfdh);
  111         bfdParams->bfdh = NULL;
  112     }
  113 }
  114 
  115 void arch_bfdDemangle(funcs_t* funcs, size_t funcCnt) {
  116     /* From -liberty, should be depended on by (included with) libbfd */
  117     __attribute__((weak)) char* cplus_demangle(const char* mangled, int options);
  118     if (!cplus_demangle) {
  119         return;
  120     }
  121     for (size_t i = 0; i < funcCnt; i++) {
  122         if (strncmp(funcs[i].func, "_Z", 2) == 0) {
  123             char* new_name = cplus_demangle(funcs[i].func, 0);
  124             if (new_name) {
  125                 snprintf(funcs[i].func, sizeof(funcs[i].func), "%s", new_name);
  126                 free(new_name);
  127             }
  128         }
  129     }
  130 }
  131 
  132 static struct bfd_section* arch_getSectionForPc(bfd* bfdh, uint64_t pc) {
  133     for (struct bfd_section* section = bfdh->sections; section; section = section->next) {
  134         uintptr_t vma = (uintptr_t)bfd_get_section_vma(bfdh, section);
  135         uintptr_t sz = (uintptr_t)bfd_get_section_size(section);
  136         if ((pc > vma) && (pc < (vma + sz))) {
  137             return section;
  138         }
  139     }
  140     return NULL;
  141 }
  142 
  143 void arch_bfdResolveSyms(pid_t pid, funcs_t* funcs, size_t num) {
  144     /* Guess what? libbfd is not multi-threading safe */
  145     MX_SCOPED_LOCK(&arch_bfd_mutex);
  146 
  147     bfd_init();
  148 
  149     __block bfd_t bfdParams = {
  150         .bfdh = NULL,
  151         .syms = NULL,
  152         .dsyms = NULL,
  153     };
  154 
  155     if (arch_bfdInit(pid, &bfdParams) == false) {
  156         return;
  157     }
  158 
  159     const char* func;
  160     const char* file;
  161     unsigned int line;
  162     for (unsigned int i = 0; i < num; i++) {
  163         snprintf(funcs[i].func, sizeof(funcs->func), "UNKNOWN");
  164         if (funcs[i].pc == NULL) {
  165             continue;
  166         }
  167         struct bfd_section* section = arch_getSectionForPc(bfdParams.bfdh, (uintptr_t)funcs[i].pc);
  168         if (section == NULL) {
  169             continue;
  170         }
  171 
  172         long sec_offset = (long)funcs[i].pc - bfd_get_section_vma(bfdParams.bfdh, section);
  173 
  174         if (bfd_find_nearest_line(
  175                 bfdParams.bfdh, section, bfdParams.syms, sec_offset, &file, &func, &line) == TRUE) {
  176             snprintf(funcs[i].func, sizeof(funcs->func), "%s", func ? func : "");
  177             snprintf(funcs[i].file, sizeof(funcs->file), "%s", file ? file : "");
  178             funcs[i].line = line;
  179         }
  180         if (bfd_find_nearest_line(
  181                 bfdParams.bfdh, section, bfdParams.syms, sec_offset, &file, &func, &line) == TRUE) {
  182             snprintf(funcs[i].func, sizeof(funcs->func), "%s", func ? func : "");
  183             snprintf(funcs[i].file, sizeof(funcs->file), "%s", file ? file : "");
  184             funcs[i].line = line;
  185         }
  186     }
  187 
  188     arch_bfdDestroy(&bfdParams);
  189 }
  190 
  191 static int arch_bfdFPrintF(void* buf, const char* fmt, ...) {
  192     va_list args;
  193     va_start(args, fmt);
  194     int ret = util_vssnprintf(buf, _HF_INSTR_SZ, fmt, args);
  195     va_end(args);
  196 
  197     return ret;
  198 }
  199 
  200 void arch_bfdDisasm(pid_t pid, uint8_t* mem, size_t size, char* instr) {
  201     MX_SCOPED_LOCK(&arch_bfd_mutex);
  202 
  203     bfd_init();
  204 
  205     char fname[PATH_MAX];
  206     snprintf(fname, sizeof(fname), "/proc/%d/exe", pid);
  207     bfd* bfdh = bfd_openr(fname, NULL);
  208     if (bfdh == NULL) {
  209         LOG_W("bfd_openr('/proc/%d/exe') failed", pid);
  210         return;
  211     }
  212 
  213     if (!bfd_check_format(bfdh, bfd_object)) {
  214         LOG_W("bfd_check_format() failed");
  215         bfd_close(bfdh);
  216         return;
  217     }
  218 #if defined(_HF_BFD_GE_2_29)
  219     disassembler_ftype disassemble =
  220         disassembler(bfd_get_arch(bfdh), bfd_little_endian(bfdh) ? FALSE : TRUE, 0, NULL);
  221 #else
  222     disassembler_ftype disassemble = disassembler(bfdh);
  223 #endif  // defined(_HD_BFD_GE_2_29)
  224     if (disassemble == NULL) {
  225         LOG_W("disassembler() failed");
  226         bfd_close(bfdh);
  227         return;
  228     }
  229 
  230     struct disassemble_info info;
  231     init_disassemble_info(&info, instr, arch_bfdFPrintF);
  232     info.arch = bfd_get_arch(bfdh);
  233     info.mach = bfd_get_mach(bfdh);
  234     info.buffer = mem;
  235     info.buffer_length = size;
  236     info.section = NULL;
  237     info.endian = bfd_little_endian(bfdh) ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
  238     disassemble_init_for_target(&info);
  239 
  240     strcpy(instr, "");
  241     if (disassemble(0, &info) <= 0) {
  242         snprintf(instr, _HF_INSTR_SZ, "[DIS-ASM_FAILURE]");
  243     }
  244 
  245     bfd_close(bfdh);
  246 }
  247 
  248 #endif /*  !defined(_HF_LINUX_NO_BFD)  */