📄 objdump.c
字号:
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;}/* Pseudo FILE object for strings. */typedef struct{ char *buffer; size_t size; char *current;} SFILE;/* sprintf to a "stream" */static int#ifdef ANSI_PROTOTYPESobjdump_sprintf (SFILE *f, const char *format, ...)#elseobjdump_sprintf (va_alist) va_dcl#endif{#ifndef ANSI_PROTOTYPES SFILE *f; const char *format;#endif char *buf; va_list args; size_t n;#ifdef ANSI_PROTOTYPES va_start (args, format);#else va_start (args); f = va_arg (args, SFILE *); format = va_arg (args, const char *);#endif vasprintf (&buf, format, args); va_end (args); if (buf == NULL) { fatal (_("Out of virtual memory")); } n = strlen (buf); while ((size_t) ((f->buffer + f->size) - f->current) < n + 1) { size_t curroff; curroff = f->current - f->buffer; f->size *= 2; f->buffer = xrealloc (f->buffer, f->size); f->current = f->buffer + curroff; } memcpy (f->current, buf, n); f->current += n; f->current[0] = '\0'; free (buf); return n;}/* The number of zeroes we want to see before we start skipping them. The number is arbitrarily chosen. */#define SKIP_ZEROES (8)/* The number of zeroes to skip at the end of a section. If the number of zeroes at the end is between SKIP_ZEROES_AT_END and SKIP_ZEROES, they will be disassembled. If there are fewer than SKIP_ZEROES_AT_END, they will be skipped. This is a heuristic attempt to avoid disassembling zeroes inserted by section alignment. */#define SKIP_ZEROES_AT_END (3)/* 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; 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; 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; sprintf_vma (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; 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) show_line (aux->abfd, section, addr_offset); if (! prefix_addresses) { char *s; sprintf_vma (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; sprintf_vma (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");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -