From 4a71579b757d3a2eb6902c84391f429838ad4912 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Thu, 30 Jan 2020 12:33:44 -0300 Subject: git subrepo clone https://git.savannah.gnu.org/git/lightning.git deps/lightning subrepo: subdir: "deps/lightning" merged: "b0b8eb5" upstream: origin: "https://git.savannah.gnu.org/git/lightning.git" branch: "master" commit: "b0b8eb5" git-subrepo: version: "0.4.1" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "a04d8c2" --- deps/lightning/lib/jit_disasm.c | 429 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 429 insertions(+) create mode 100644 deps/lightning/lib/jit_disasm.c (limited to 'deps/lightning/lib/jit_disasm.c') diff --git a/deps/lightning/lib/jit_disasm.c b/deps/lightning/lib/jit_disasm.c new file mode 100644 index 0000000..15b91b9 --- /dev/null +++ b/deps/lightning/lib/jit_disasm.c @@ -0,0 +1,429 @@ +/* + * Copyright (C) 2012-2019 Free Software Foundation, Inc. + * + * This file is part of GNU lightning. + * + * GNU lightning is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU lightning is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * Authors: + * Paulo Cesar Pereira de Andrade + */ + +#include +#include +#if DISASSEMBLER +# include +#endif + +/* + * Prototypes + */ +#if DISASSEMBLER +static int +disasm_compare_symbols(const void *ap, const void *bp); + +static void +disasm_print_address(bfd_vma addr, struct disassemble_info *info); + +#define disassemble(u, v) _disassemble(_jit, u, v) +static void +_disassemble(jit_state_t *_jit, jit_pointer_t code, jit_int32_t length); +#endif + +/* + * Initialization + */ +#if DISASSEMBLER +static bfd *disasm_bfd; +static disassemble_info disasm_info; +static disassembler_ftype disasm_print; +static asymbol **disasm_symbols; +static asymbol *disasm_synthetic; +static long disasm_num_symbols; +static long disasm_num_synthetic; +static jit_state_t *disasm_jit; +#define disasm_stream stdout +#endif + +/* + * Implementation + */ +void +jit_init_debug(const char *progname) +{ +#if DISASSEMBLER + bfd_init(); + + if (progname) + disasm_bfd = bfd_openr(progname, NULL); + if (disasm_bfd == NULL) { +#if defined(__linux__) + disasm_bfd = bfd_openr("/proc/self/exe", NULL); + if (disasm_bfd == NULL) +#endif + return; + } + bfd_check_format(disasm_bfd, bfd_object); + bfd_check_format(disasm_bfd, bfd_archive); + INIT_DISASSEMBLE_INFO(disasm_info, disasm_stream, fprintf); +# if defined(__i386__) || defined(__x86_64__) + disasm_info.arch = bfd_arch_i386; +# if defined(__x86_64__) +# if __WORDSIZE == 32 + disasm_info.mach = bfd_mach_x64_32; +# else + disasm_info.mach = bfd_mach_x86_64; +# endif +# else + disasm_info.mach = bfd_mach_i386_i386; +# endif +# endif +# if defined(__powerpc__) + disasm_info.arch = bfd_arch_powerpc; + disasm_info.mach = bfd_mach_ppc64; +# if HAVE_DISASSEMBLE_INIT_FOR_TARGET + disassemble_init_for_target(&disasm_info); +# elif HAVE_DISASSEMBLE_INIT_POWERPC + disassemble_init_powerpc(&disasm_info); +# endif +# if defined(__powerpc64__) + disasm_info.disassembler_options = "64"; +# endif +# if HAVE_DISASSEMBLE_INIT_FOR_TARGET + disassemble_init_for_target(&disasm_info); +# elif HAVE_DISASSEMBLE_INIT_POWERPC + disassemble_init_powerpc(&disasm_info); +# endif +# endif +# if defined(__sparc__) + disasm_info.endian = disasm_info.display_endian = BFD_ENDIAN_BIG; +# endif +# if defined(__s390__) || defined(__s390x__) + disasm_info.arch = bfd_arch_s390; +# if __WORDSIZE == 32 + disasm_info.mach = bfd_mach_s390_31; +# else + disasm_info.mach = bfd_mach_s390_64; +# endif + disasm_info.endian = disasm_info.display_endian = BFD_ENDIAN_BIG; + disasm_info.disassembler_options = "zarch"; +# endif +# if defined(__alpha__) + disasm_info.arch = bfd_arch_alpha; + disasm_info.mach = bfd_mach_alpha_ev6; +# endif +# if defined(__hppa__) + disasm_info.arch = bfd_arch_hppa; + disasm_info.mach = bfd_mach_hppa10; +# endif +# if defined(__riscv) + disasm_info.arch = bfd_arch_riscv; +# if __WORDSIZE == 32 + disasm_info.mach = bfd_mach_riscv32; +# else + disasm_info.mach = bfd_mach_riscv64; +# endif +# endif + disasm_info.print_address_func = disasm_print_address; + +# if BINUTILS_2_29 + disasm_print = disassembler(disasm_info.arch, __BYTE_ORDER == __BIG_ENDIAN, + disasm_info.mach, disasm_bfd); +# else + disasm_print = disassembler(disasm_bfd); +# endif + assert(disasm_print); + + if (bfd_get_file_flags(disasm_bfd) & HAS_SYMS) { + asymbol **in; + asymbol **out; + asymbol *symbol; + long offset; + long sym_count; + long dyn_count; + long sym_storage; + long dyn_storage; + + if ((sym_storage = bfd_get_symtab_upper_bound(disasm_bfd)) >= 0) { + + if (bfd_get_file_flags(disasm_bfd) & DYNAMIC) { + dyn_storage = bfd_get_dynamic_symtab_upper_bound(disasm_bfd); +# if defined(__alpha__) + /* XXX */ + if (dyn_storage < 0) + dyn_storage = 0; +# else + assert(dyn_storage >= 0); +# endif + } + else + dyn_storage = 0; + + jit_alloc((jit_pointer_t *)&disasm_symbols, + (sym_storage + dyn_storage) * sizeof(asymbol *)); + sym_count = bfd_canonicalize_symtab(disasm_bfd, disasm_symbols); + assert(sym_count >= 0); + if (dyn_storage) { + dyn_count = bfd_canonicalize_dynamic_symtab(disasm_bfd, + disasm_symbols + + sym_count); + assert(dyn_count >= 0); + } + else + dyn_count = 0; + disasm_num_symbols = sym_count + dyn_count; + + disasm_num_synthetic = bfd_get_synthetic_symtab(disasm_bfd, + sym_count, + disasm_symbols, + dyn_count, + disasm_symbols + + sym_count, + &disasm_synthetic); + if (disasm_num_synthetic > 0) { + jit_realloc((jit_pointer_t *)&disasm_symbols, + (sym_storage + dyn_storage) * sizeof(asymbol *), + (sym_storage + dyn_storage + disasm_num_synthetic) * + sizeof(asymbol *)); + for (offset = 0; offset < disasm_num_synthetic; offset++) + disasm_symbols[disasm_num_symbols++] = + disasm_synthetic + offset; + } + + /* remove symbols not useful for disassemble */ + in = out = disasm_symbols; + for (offset = 0; offset < disasm_num_symbols; offset++) { + symbol = *in++; + if (symbol->name && + symbol->name[0] != '\0' && + !(symbol->flags & (BSF_DEBUGGING | BSF_SECTION_SYM)) && + !bfd_is_und_section(symbol->section) && + !bfd_is_com_section(symbol->section)) + *out++ = symbol; + } + disasm_num_symbols = out - disasm_symbols; + qsort(disasm_symbols, disasm_num_symbols, + sizeof(asymbol *), disasm_compare_symbols); + } + } +#endif +} + +void +jit_finish_debug(void) +{ +#if DISASSEMBLER + if (disasm_synthetic) + jit_free((jit_pointer_t *)&disasm_synthetic); + if (disasm_symbols) + jit_free((jit_pointer_t *)&disasm_symbols); + if (disasm_bfd) + bfd_close (disasm_bfd); +#endif +} + +void +_jit_disassemble(jit_state_t *_jit) +{ +#if DISASSEMBLER + if (disasm_bfd) { +# if defined(__arm__) + /* FIXME add mapping for prolog switching to arm and possible jump + * before first prolog also in arm mode */ + disasm_info.disassembler_options = jit_cpu.thumb ? "force-thumb" : ""; +# endif + + disassemble(_jit->code.ptr, _jit->pc.uc - _jit->code.ptr); + } +#endif +} + +#if DISASSEMBLER +/* Based on objdump source */ +static int +disasm_compare_symbols(const void *ap, const void *bp) +{ + const asymbol *a = *(const asymbol **)ap; + const asymbol *b = *(const asymbol **)bp; + + if (bfd_asymbol_value(a) > bfd_asymbol_value(b)) + return (1); + if (bfd_asymbol_value(a) < bfd_asymbol_value(b)) + return (-1); + return (0); +} + +#if __WORDSIZE == 32 +# define address_buffer_length 16 +# define address_buffer_format "%llx" +#else +# define address_buffer_length 32 +# define address_buffer_format "%lx" +#endif +static void +disasm_print_address(bfd_vma addr, struct disassemble_info *info) +{ + char *name; + char *file; + int line; + char buffer[address_buffer_length]; + + sprintf(buffer, address_buffer_format, (long long)addr); + (*info->fprintf_func)(info->stream, "0x%s", buffer); + +# define _jit disasm_jit +# undef jit_pointer_p +# define jit_pointer_p(u) \ + ((u) >= _jit->code.ptr && (u) < _jit->pc.uc) + if (jit_pointer_p((jit_uint8_t *)(jit_word_t)addr)) { + if (jit_get_note((jit_uint8_t *)(jit_word_t)addr, &name, &file, &line)) + (*info->fprintf_func)(info->stream, " %s:%s:%d", + name ? name : "", + file ? file : "", + line); + } +# undef jit_pointer_p +# undef _jit + else if (disasm_num_symbols) { + long low; + long high; + long offset; + asymbol *symbol; + + low = 0; + high = disasm_num_symbols; + do { + offset = (low + high) >> 1; + symbol = disasm_symbols[offset]; + if (bfd_asymbol_value(symbol) > addr) + high = offset - 1; + else if (bfd_asymbol_value(symbol) < addr) + low = offset + 1; + else + break; + } while (low < high); + + if (offset >= 0 && offset < disasm_num_symbols) { + if (bfd_asymbol_value(symbol) < addr) { + while (++offset < disasm_num_symbols) { + symbol = disasm_symbols[offset]; + if (bfd_asymbol_value(symbol) >= addr) + break; + } + } + else if (bfd_asymbol_value(symbol) > addr) { + while (offset--) { + if (bfd_asymbol_value(disasm_symbols[offset]) < addr) + break; + symbol = disasm_symbols[offset]; + } + } + if (bfd_asymbol_value(symbol) == addr) + (*info->fprintf_func)(info->stream, " # %s", symbol->name); + } + } +} + +static void +_disassemble(jit_state_t *_jit, jit_pointer_t code, jit_int32_t length) +{ + int bytes; + char *name, *old_name; + char *file, *old_file; + int line, old_line; +#if __arm__ + jit_int32_t offset; + jit_bool_t data_info; + jit_int32_t data_offset; +#endif + bfd_vma pc = (jit_uword_t)code; + bfd_vma end = (jit_uword_t)code + length; + char buffer[address_buffer_length]; +#if DEVEL_DISASSEMBLER + jit_node_t *node; + jit_uword_t prevw; +#endif + +#if __arm__ + data_info = _jitc && _jitc->data_info.ptr; + data_offset = 0; +#endif + disasm_info.buffer = code; + disasm_info.buffer_vma = (jit_uword_t)code; + disasm_info.buffer_length = length; + old_file = old_name = NULL; + old_line = 0; + disasm_jit = _jit; +#if DEVEL_DISASSEMBLER + node = _jitc->head; + prevw = pc; +#endif + while (pc < end) { +#if DEVEL_DISASSEMBLER + while (node && (jit_uword_t)(prevw + node->offset) < (jit_uword_t)pc) { + prevw += node->offset; + node = node->next; + } + while (node && (jit_uword_t)(prevw + node->offset) == (jit_uword_t)pc) { + jit_print_node(node); + fputc('\n', stdout); + prevw += node->offset; + node = node->next; + } +#endif +#if __arm__ + again: + if (data_info) { + while (_jitc->data_info.ptr[data_offset].code < pc) { + if (++data_offset >= _jitc->data_info.length) { + data_info = 0; + goto again; + } + } + if (pc == _jitc->data_info.ptr[data_offset].code) { + offset = _jitc->data_info.ptr[data_offset].length; + for (; offset >= 4; offset -= 4, pc += 4) { + bytes = sprintf(buffer, address_buffer_format, pc); + (*disasm_info.fprintf_func)(disasm_stream, + "%*c0x%s\t.data\t0x%08x\n", + 16 - bytes, ' ', buffer, + *(jit_uint32_t *) + (jit_uint32_t)pc); + } + /* reset disassemble information instead of attempting + * to hack the arm specific backend data structures to + * tell it to forward the required number of bytes. */ + disasm_info.buffer = (jit_pointer_t)(jit_uint32_t)pc; + disasm_info.buffer_vma = (jit_uword_t)pc; + if ((disasm_info.buffer_length = end - pc) <= 0) + break; + } + } +#endif + if (jit_get_note((jit_uint8_t *)(jit_word_t)pc, &name, &file, &line) && + (name != old_name || file != old_file || line != old_line)) { + (*disasm_info.fprintf_func)(disasm_stream, "# %s:%s:%d\n", + name ? name : "", + file ? file : "", + line); + old_name = name; + old_file = file; + old_line = line; + } + + bytes = sprintf(buffer, address_buffer_format, (long long)pc); + (*disasm_info.fprintf_func)(disasm_stream, "%*c0x%s\t", + 16 - bytes, ' ', buffer); + pc += (*disasm_print)(pc, &disasm_info); + putc('\n', disasm_stream); + } +} +#endif -- cgit v1.2.3