dis_main.c revision f7184619589931c4b827180c213074c470f08a8f
2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 2N/A * Use is subject to license terms. 2N/A * Copyright 2011 Jason King. All rights reserved. 2N/A * Copyright 2012 Joshua M. Clulow <josh@sysmgr.org> 2N/Aint g_doall;
/* true if no functions or sections were given */ 2N/A * Section options for -d, -D, and -s 2N/A * libdisasm callback data. Keeps track of current data (function or section) 2N/A * and offset within that data. 2N/A * Given a symbol+offset as returned by dis_tgt_lookup(), print an appropriately 2N/A * formatted symbol, based on the offset and current setttings. 2N/A * Determine if we are on an architecture with fixed-size instructions, 2N/A * and if so, what size they are. 2N/A * The main disassembly routine. Given a fixed-sized buffer and starting 2N/A * address, disassemble the data using the supplied target and libdisasm handle. 2N/A * Since we know instructions are fixed size, we 2N/A * always know the address of the next instruction 2N/A "*** invalid opcode ***");
2N/A "*** invalid opcode ***");
2N/A * On architectures with variable sized instructions 2N/A * we have no way to figure out where the next 2N/A * instruction starts if we encounter an invalid 2N/A * instruction. Instead we print the rest of the 2N/A * instruction stream as hex until we reach the 2N/A * next valid symbol in the section. 2N/A * Print out the line as: 2N/A * address: bytes text 2N/A * If there are more than 6 bytes in any given instruction, 2N/A * spread the bytes across two lines. We try to get symbolic 2N/A * information for the address, but if that fails we print out 2N/A * the numeric address instead. 2N/A * We try to keep the address portion of the text aligned at 2N/A * MINSYMWIDTH characters. If we are disassembling a function 2N/A * with a long name, this can be annoying. So we pick a width 2N/A * based on the maximum width that the current symbol can be. 2N/A * This at least produces text aligned within each function. 2N/A * If we've crossed a new function boundary, print out the 2N/A * function name on a blank line. 2N/A /* trailing spaces for missing bytes */ 2N/A /* contents of disassembly */ 2N/A /* excess bytes that spill over onto subsequent lines */ 2N/A * libdisasm wrapper around symbol lookup. Invoke the target-specific lookup 2N/A * function, and convert the result using getsymname(). 2N/A * If NULL symbol is returned, getsymname takes care of 2N/A * printing appropriate address in buf instead of symbol. 2N/A * libdisasm wrapper around target reading. libdisasm will always read data 2N/A * in order, so update our current offset within the buffer appropriately. 2N/A * We only support reading from within the current object; libdisasm should 2N/A * never ask us to do otherwise. 2N/A * Routine to dump raw data in a human-readable format. Used by the -d and -D 2N/A * options. We model our output after the xxd(1) program, which gives nicely 2N/A * formatted output, along with an ASCII translation of the result. 2N/A * Determine if the address given to us fits in 32-bit range, in which 2N/A * case use a 4-byte width. 2N/A * Display leading address 2N/A * Print out data in two-byte chunks. If the current address 2N/A * is before the starting address or after the end of the 2N/A * section, print spaces. 2N/A for (i = 0; i <
16; i++) {
2N/A * Print out the ASCII representation 2N/A for (i = 0; i <
16; i++) {
2N/A * Disassemble a section implicitly specified as part of a file. This function 2N/A * is called for all sections when no other flags are specified. We ignore any 2N/A * data sections, and print out only those sections containing text. 2N/A /* ignore data sections */ 2N/A * Structure passed to dis_named_{section,function} which keeps track of both 2N/A * the target and the libdisasm handle. 2N/A * Disassemble a section explicitly named with -s, -d, or -D. The 'type' 2N/A * argument contains the type of argument given. Pass the data onto the 2N/A * appropriate helper routine. * Disassemble a function explicitly specified with '-F'. The 'type' argument * Disassemble a complete file. First, we determine the type of the file based * on the ELF machine type, and instantiate a version of the disassembler * appropriate for the file. We then resolve any named sections or functions * against the file, and iterate over the results (or all sections if no flags * First, initialize the target * A given file may contain multiple targets (if it is an archive, for * example). We iterate over all possible targets if this is the case. * Eventually, this should probably live within libdisasm, and * we should be able to disassemble targets from different * architectures. For now, we only support objects as the warn(
"invalid E_IDENT field for SPARC object");
warn(
"invalid E_IDENT field for SPARC object");
warn(
"invalid E_IDENT field for SPARC object");
* If ET_REL (.o), printing immediate symbols is likely to * result in garbage, as symbol lookups on unrelocated * immediates find false and useless matches. (
void)
printf(
"\narchive member %s\n",
* Instantiate a libdisasm handle based on the file type. die(
"%s: failed to initialize disassembler: %s",
* With no arguments, iterate over all sections and * disassemble only those that contain text. * If sections or functions were explicitly specified, * resolve those names against the object, and iterate * over just the resulting data. (
void)
fprintf(
stderr,
"\t[-D sec] [-F function] [-t sec] file ..\n");
* The '-l foo' option historically would attempt to * environment variable has never been supported or * documented for our linker. However, until this * option is formally EOLed, we have to support it. * The '-L' option historically would attempt to read * the .debug section of the target to determine source * line information in order to annotate the output. * No compiler has emitted these sections in many years, * and the option has never done what it purported to * do. We silently consume the option for (
void)
printf(
"Solaris disassembler version 1.0\n");
warn(
"no objects specified");
* See comment for 'l' option, above. for (i = 0; i <
argc; i++)