📄 load.c
字号:
static int file_start_context = 0; /* --file-start-context */#define SHOW_PRECEDING_CONTEXT_LINES (5)/* Show the line number, or the source line, in a dissassembly listing. */static voidshow_line (abfd, section, addr_offset) bfd *abfd; asection *section; bfd_vma addr_offset;{ const char *filename; const char *functionname; unsigned int line; if (! with_line_numbers && ! with_source_code) return; if (! bfd_find_nearest_line (abfd, section, syms, addr_offset, &filename, &functionname, &line)) return; if (filename != NULL && *filename == '\0') filename = NULL; if (functionname != NULL && *functionname == '\0') functionname = NULL; if (with_line_numbers) { if (functionname != NULL && (prev_functionname == NULL || strcmp (functionname, prev_functionname) != 0)) printf ("%s():\n", functionname); if (line > 0 && line != prev_line) printf ("%s:%u\n", filename == NULL ? "???" : filename, line); } if (with_source_code && filename != NULL && line > 0) { struct print_file_list **pp, *p; for (pp = &print_files; *pp != NULL; pp = &(*pp)->next) if (strcmp ((*pp)->filename, filename) == 0) break; p = *pp; if (p != NULL) { if (p != print_files) { int l; /* We have reencountered a file name which we saw earlier. This implies that either we are dumping out code from an included file, or the same file was linked in more than once. There are two common cases of an included file: inline functions in a header file, and a bison or flex skeleton file. In the former case we want to just start printing (but we back up a few lines to give context); in the latter case we want to continue from where we left off. I can't think of a good way to distinguish the cases, so I used a heuristic based on the file name. */ if (strcmp (p->filename + strlen (p->filename) - 2, ".h") != 0) l = p->line; else { l = line - SHOW_PRECEDING_CONTEXT_LINES; if (l < 0) l = 0; } if (p->f == NULL) { p->f = fopen (p->filename, "r"); p->line = 0; } if (p->f != NULL) skip_to_line (p, l, FALSE); if (print_files->f != NULL) { fclose (print_files->f); print_files->f = NULL; } } if (p->f != NULL) { skip_to_line (p, line, TRUE); *pp = p->next; p->next = print_files; print_files = p; } } else { FILE *f; f = fopen (filename, "r"); if (f != NULL) { int l; p = ((struct print_file_list *) xmalloc (sizeof (struct print_file_list))); p->filename = xmalloc (strlen (filename) + 1); strcpy (p->filename, filename); p->line = 0; p->f = f; if (print_files != NULL && print_files->f != NULL) { fclose (print_files->f); print_files->f = NULL; } p->next = print_files; print_files = p; if (file_start_context) l = 0; else l = line - SHOW_PRECEDING_CONTEXT_LINES; if (l < 0) l = 0; skip_to_line (p, l, FALSE); if (p->f != NULL) skip_to_line (p, line, TRUE); } } } if (functionname != NULL && (prev_functionname == NULL || strcmp (functionname, prev_functionname) != 0)) { if (prev_functionname != NULL) free (prev_functionname); prev_functionname = xmalloc (strlen (functionname) + 1); strcpy (prev_functionname, functionname); } if (line > 0 && line != prev_line) prev_line = line;}/* Disassemble some data in memory between given values. */static voiddisassemble_bytes (info, disassemble_fn, insns, data, start_offset, stop_offset, relppp, relppend) struct disassemble_info *info; disassembler_ftype disassemble_fn; bfd_boolean insns; bfd_byte *data; bfd_vma start_offset; bfd_vma stop_offset; arelent ***relppp; arelent **relppend;{ struct objdump_disasm_info *aux; asection *section; int octets_per_line; bfd_boolean done_dot; int skip_addr_chars; bfd_vma addr_offset; int opb = info->octets_per_byte; aux = (struct objdump_disasm_info *) info->application_data; section = aux->sec; if (insns) octets_per_line = 4; else octets_per_line = 16; /* Figure out how many characters to skip at the start of an address, to make the disassembly look nicer. We discard leading zeroes in chunks of 4, ensuring that there is always a leading zero remaining. */ skip_addr_chars = 0; if (! prefix_addresses) { char buf[30]; char *s; bfd_sprintf_vma (aux->abfd, buf, (section->vma + bfd_section_size (section->owner, section) / opb)); s = buf; while (s[0] == '0' && s[1] == '0' && s[2] == '0' && s[3] == '0' && s[4] == '0') { skip_addr_chars += 4; s += 4; } } info->insn_info_valid = 0; done_dot = FALSE; addr_offset = start_offset; while (addr_offset < stop_offset) { bfd_vma z; int octets = 0; bfd_boolean need_nl = FALSE; /* If we see more than SKIP_ZEROES octets of zeroes, we just print `...'. */ for (z = addr_offset * opb; z < stop_offset * opb; z++) if (data[z] != 0) break; if (! disassemble_zeroes && (info->insn_info_valid == 0 || info->branch_delay_insns == 0) && (z - addr_offset * opb >= SKIP_ZEROES || (z == stop_offset * opb && z - addr_offset * opb < SKIP_ZEROES_AT_END))) { printf ("\t...\n"); /* If there are more nonzero octets to follow, we only skip zeroes in multiples of 4, to try to avoid running over the start of an instruction which happens to start with zero. */ if (z != stop_offset * opb) z = addr_offset * opb + ((z - addr_offset * opb) &~ 3); octets = z - addr_offset * opb; } else { char buf[50]; SFILE sfile; int bpc = 0; int pb = 0; done_dot = FALSE; if (with_line_numbers || with_source_code) /* The line number tables will refer to unadjusted section VMAs, so we must undo any VMA modifications when calling show_line. */ show_line (aux->abfd, section, addr_offset - adjust_section_vma); if (! prefix_addresses) { char *s; bfd_sprintf_vma (aux->abfd, buf, section->vma + addr_offset); for (s = buf + skip_addr_chars; *s == '0'; s++) *s = ' '; if (*s == '\0') *--s = '0'; printf ("%s:\t", buf + skip_addr_chars); } else { aux->require_sec = TRUE; objdump_print_address (section->vma + addr_offset, info); aux->require_sec = FALSE; putchar (' '); } if (insns) { sfile.size = 120; sfile.buffer = xmalloc (sfile.size); sfile.current = sfile.buffer; info->fprintf_func = (fprintf_ftype) objdump_sprintf; info->stream = (FILE *) &sfile; info->bytes_per_line = 0; info->bytes_per_chunk = 0;#ifdef DISASSEMBLER_NEEDS_RELOCS /* FIXME: This is wrong. It tests the number of octets in the last instruction, not the current one. */ if (*relppp < relppend && (**relppp)->address >= addr_offset && (**relppp)->address <= addr_offset + octets / opb) info->flags = INSN_HAS_RELOC; else#endif info->flags = 0; octets = (*disassemble_fn) (section->vma + addr_offset, info); info->fprintf_func = (fprintf_ftype) fprintf; info->stream = stdout; if (info->bytes_per_line != 0) octets_per_line = info->bytes_per_line; if (octets < 0) { if (sfile.current != sfile.buffer) printf ("%s\n", sfile.buffer); free (sfile.buffer); break; } } else { bfd_vma j; octets = octets_per_line; if (addr_offset + octets / opb > stop_offset) octets = (stop_offset - addr_offset) * opb; for (j = addr_offset * opb; j < addr_offset * opb + octets; ++j) { if (isprint (data[j])) buf[j - addr_offset * opb] = data[j]; else buf[j - addr_offset * opb] = '.'; } buf[j - addr_offset * opb] = '\0'; } if (prefix_addresses ? show_raw_insn > 0 : show_raw_insn >= 0) { bfd_vma j; /* If ! prefix_addresses and ! wide_output, we print octets_per_line octets per line. */ pb = octets; if (pb > octets_per_line && ! prefix_addresses && ! wide_output) pb = octets_per_line; if (info->bytes_per_chunk) bpc = info->bytes_per_chunk; else bpc = 1; for (j = addr_offset * opb; j < addr_offset * opb + pb; j += bpc) { int k; if (bpc > 1 && info->display_endian == BFD_ENDIAN_LITTLE) { for (k = bpc - 1; k >= 0; k--) printf ("%02x", (unsigned) data[j + k]); putchar (' '); } else { for (k = 0; k < bpc; k++) printf ("%02x", (unsigned) data[j + k]); putchar (' '); } } for (; pb < octets_per_line; pb += bpc) { int k; for (k = 0; k < bpc; k++) printf (" "); putchar (' '); } /* Separate raw data from instruction by extra space. */ if (insns) putchar ('\t'); else printf (" "); } if (! insns) printf ("%s", buf); else { printf ("%s", sfile.buffer); free (sfile.buffer); } if (prefix_addresses ? show_raw_insn > 0 : show_raw_insn >= 0) { while (pb < octets) { bfd_vma j; char *s; putchar ('\n'); j = addr_offset * opb + pb; bfd_sprintf_vma (aux->abfd, buf, section->vma + j / opb); for (s = buf + skip_addr_chars; *s == '0'; s++) *s = ' '; if (*s == '\0') *--s = '0'; printf ("%s:\t", buf + skip_addr_chars); pb += octets_per_line; if (pb > octets) pb = octets; for (; j < addr_offset * opb + pb; j += bpc) { int k; if (bpc > 1 && info->display_endian == BFD_ENDIAN_LITTLE) { for (k = bpc - 1; k >= 0; k--) printf ("%02x", (unsigned) data[j + k]); putchar (' '); } else { for (k = 0; k < bpc; k++) printf ("%02x", (unsigned) data[j + k]); putchar (' '); } } } } if (!wide_output) putchar ('\n'); else need_nl = TRUE; } if ((section->flags & SEC_RELOC) != 0#ifndef DISASSEMBLER_NEEDS_RELOCS && dump_reloc_info#endif ) { while ((*relppp) < relppend && ((**relppp)->address >= (bfd_vma) addr_offset && (**relppp)->address < (bfd_vma) addr_offset + octets / opb))#ifdef DISASSEMBLER_NEEDS_RELOCS if (! dump_reloc_info) ++(*relppp); else#endif { arelent *q; q = **relppp; if (wide_output) putchar ('\t'); else printf ("\t\t\t"); objdump_print_value (section->vma + q->address, info, TRUE); printf (": %s\t", q->howto->name); if (q->sym_ptr_ptr == NULL || *q->sym_ptr_ptr == NULL) printf ("*unknown*"); else { const char *sym_name; sym_name = bfd_asymbol_name (*q->sym_ptr_ptr); if (sym_name != NULL && *sym_name != '\0') objdump_print_symname (aux->abfd, info, *q->sym_ptr_ptr); else { asection *sym_sec; sym_sec = bfd_get_section (*q->sym_ptr_ptr); sym_name = bfd_get_section_name (aux->abfd, sym_sec); if (sym_name == NULL || *sym_name == '\0') sym_name = "*unknown*"; printf ("%s", sym_name); } } if (q->addend) { printf ("+0x"); objdump_print_value (q->addend, info, TRUE); } printf ("\n"); need_nl = FALSE; ++(*relppp); } } if (need_nl) printf ("\n"); addr_offset += octets / opb; }}/* Disassemble the contents of an object file. */static voiddisassemble_data (abfd) bfd *abfd;{ unsigned long addr_offset; disassembler_ftype disassemble_fn; struct disassemble_info disasm_info; struct objdump_disasm_info aux; asection *section; unsigned int opb; print_files = NULL; prev_functionname = NULL; prev_line = -1; /* We make a copy of syms to sort. We don't want to sort syms because that will screw up the relocs. */ sorted_syms = (asymbol **) xmalloc (symcount * sizeof (asymbol *)); memcpy (sorted_syms, syms, symcount * sizeof (asymbol *)); sorted_symcount = remove_useless_symbols (sorted_syms, symcount); /* Sort the symbols into section and symbol order. */ qsort (sorted_syms, sorted_symcount, sizeof (asymbol *), compare_symbols); INIT_DISASSEMBLE_INFO (disasm_info, stdout, fprintf); disasm_info.application_data = (PTR) &aux; aux.abfd = abfd; aux.require_sec = FALSE; disasm_info.print_address_func = objdump_print_address; disasm_info.symbol_at_address_func = objdump_symbol_at_address; if (machine != (char *) NULL) { const bfd_arch_info_type *info = bfd_scan_arch (machine); if (info == NULL) fatal ("Can't use supplied machine %s", machine); abfd->arch_info = info; } if (endian != BFD_ENDIAN_UNKNOWN) { struct bfd_target *xvec; xvec = (struct bfd_target *) xmalloc (sizeof (struct bfd_target)); memcpy (xvec, abfd->xvec, sizeof (struct bfd_target)); xvec->byteorder = endian; abfd->xvec = xvec; } disassemble_fn = disassembler (abfd); if (!disassemble_fn) { non_fatal ("Can't disassemble for architecture %s\n", bfd_printable_arch_mach (bfd_get_arch (abfd), 0)); exit_status = 1; return; } opb = bfd_octets_per_byte (abfd); disasm_info.flavour = bfd_get_flavour (abfd); disasm_info.arch = bfd_get_arch (abfd); disasm_info.mach = bfd_get_mach (abfd); disasm_info.disassembler_options = disassembler_options; disasm_info.octets_per_byte = opb; if (bfd_big_endian (abfd)) disasm_info.display_endian = disasm_info.endian = BFD_ENDIAN_BIG; else if (bfd_little_endian (abfd)) disasm_info.display_endian = disasm_info.endian = BFD_ENDIAN_LITTLE; else /* ??? Aborting here seems too drastic. We could default to big or little instead. */ disasm_info.endian = BFD_ENDIAN_UNKNOWN; for (section = abfd->sections; section != (asection *) NULL; section = section->next) { bfd_byte *data = NULL; bfd_size_type datasize = 0; arelent **relbuf = NULL; arelent **relpp = NULL; arelent **relppend = NULL; unsigned long stop_offset; asymbol *sym = NULL; long place = 0; if ((section->flags & SEC_LOAD) == 0 || (! disassemble_all && only == NULL && (section->flags & SEC_CODE) == 0)) continue; if (only != (char *) NULL && strcmp (only, section->name) != 0) continue; if ((section->flags & SEC_RELOC) != 0#ifndef DISASSEMBLER_NEEDS_RELOCS && dump_reloc_info#endif ) { long relsize; relsize = bfd_get_reloc_upper_bound (abfd, section); if (relsize < 0) bfd_fatal (bfd_get_filename (abfd)); if (relsize > 0) { long relcount; relbuf = (arelent **) xmalloc (relsize); relcount = bfd_canonicalize_reloc (abfd, section, relbuf, syms); if (relcount < 0) bfd_fatal (bfd_get_filename (abfd)); /* Sort the relocs by address. */ qsort (relbuf, relcount, sizeof (arelent *), compare_relocs); relpp = relbuf; relppend = relpp + relcount; /* Skip over the relocs belonging to addresses below the start address. */ if (start_address != (bfd_vma) -1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -