#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <ar.h>
#include <mach-o/ranlib.h>
#include <libc.h>
#include "stuff/bool.h"
#include "stuff/ofile.h"
#include "stuff/errors.h"
#include "stuff/allocate.h"
#include "otool.h"
#include "ofile_print.h"
#include "m68k_disasm.h"
#include "i860_disasm.h"
#include "i386_disasm.h"
#include "m88k_disasm.h"
#include "ppc_disasm.h"
#include "hppa_disasm.h"
#include "sparc_disasm.h"
char *progname = NULL;
enum bool fflag = FALSE;
enum bool aflag = FALSE;
enum bool hflag = FALSE;
enum bool lflag = FALSE;
enum bool Lflag = FALSE;
enum bool Dflag = FALSE;
enum bool tflag = FALSE;
enum bool dflag = FALSE;
enum bool oflag = FALSE;
enum bool Oflag = FALSE;
enum bool rflag = FALSE;
enum bool Tflag = FALSE;
enum bool Mflag = FALSE;
enum bool Rflag = FALSE;
enum bool Iflag = FALSE;
enum bool Hflag = FALSE;
enum bool Sflag = FALSE;
enum bool vflag = FALSE;
enum bool Vflag = FALSE;
enum bool cflag = FALSE;
enum bool iflag = FALSE;
enum bool Wflag = FALSE;
enum bool Xflag = FALSE;
enum bool Zflag = FALSE;
char *pflag = NULL;
char *segname = NULL;
char *sectname = NULL;
enum bool object_processing = FALSE;
static void usage(
void);
static void processor(
struct ofile *ofile,
char *arch_name,
void *cookie);
static void get_symbol_table_info(
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex load_commands_byte_sex,
char *object_addr,
unsigned long object_size,
struct nlist **symbols,
unsigned long *nsymbols,
char **strings,
unsigned long *strings_size);
static void get_toc_info(
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex load_commands_byte_sex,
char *object_addr,
unsigned long object_size,
struct dylib_table_of_contents **tocs,
unsigned long *ntocs);
static void get_module_table_info(
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex load_commands_byte_sex,
char *object_addr,
unsigned long object_size,
struct dylib_module **mods,
unsigned long *nmods);
static void get_ref_info(
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex load_commands_byte_sex,
char *object_addr,
unsigned long object_size,
struct dylib_reference **refs,
unsigned long *nrefs);
static void get_indirect_symbol_table_info(
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex load_commands_byte_sex,
char *object_addr,
unsigned long object_size,
unsigned long **indirect_symbols,
unsigned long *nindirect_symbols);
static enum bool get_dyst(
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex load_commands_byte_sex,
struct dysymtab_command *dyst);
static void get_hints_table_info(
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex load_commands_byte_sex,
char *object_addr,
unsigned long object_size,
struct twolevel_hint **hints,
unsigned long *nhints);
static enum bool get_hints_cmd(
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex load_commands_byte_sex,
struct twolevel_hints_command *hints_cmd);
static int sym_compare(
struct nlist *sym1,
struct nlist *sym2);
static int rel_compare(
struct relocation_info *rel1,
struct relocation_info *rel2);
static enum bool get_sect_info(
char *segname,
char *sectname,
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex load_commands_byte_sex,
char *object_addr,
unsigned long object_size,
char **sect_pointer,
unsigned long *sect_size,
unsigned long *sect_addr,
struct relocation_info **sect_relocs,
unsigned long *sect_nrelocs,
unsigned long *sect_flags);
static void print_text(
cpu_type_t cputype,
enum byte_sex object_byte_sex,
char *sect,
unsigned long size,
unsigned long addr,
struct nlist *sorted_symbols,
unsigned long nsorted_symbols,
struct nlist *symbols,
unsigned long nsymbols,
char *strings,
unsigned long strings_size,
struct relocation_info *relocs,
unsigned long nrelocs,
unsigned long *indirect_symbols,
unsigned long nindirect_symbols,
struct mach_header *mh,
struct load_command *load_commands,
enum bool disassemble,
enum bool verbose);
static void print_argstrings(
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex load_commands_byte_sex,
char *object_addr,
unsigned long object_size);
int
main(
int argc,
char **argv,
char **envp)
{
int i;
unsigned long j, nfiles;
struct arch_flag *arch_flags;
unsigned long narch_flags;
enum bool all_archs, use_member_syntax;
char **files;
progname = argv[0];
arch_flags = NULL;
narch_flags = 0;
all_archs = FALSE;
use_member_syntax = TRUE;
if(argc <= 1)
usage();
nfiles = 0;
files = allocate(sizeof(char *) * argc);
for(i = 1; i < argc; i++){
if(argv[i][0] == '-' && argv[i][1] == '\0'){
for(i += 1 ; i < argc; i++)
files[nfiles++] = argv[i];
break;
}
if(argv[i][0] != '-'){
files[nfiles++] = argv[i];
continue;
}
if(strcmp(argv[i], "-arch") == 0){
if(i + 1 == argc){
error("missing argument(s) to %s option", argv[i]);
usage();
}
if(strcmp("all", argv[i+1]) == 0){
all_archs = TRUE;
}
else{
arch_flags = reallocate(arch_flags,
(narch_flags + 1) * sizeof(struct arch_flag));
if(get_arch_from_flag(argv[i+1],
arch_flags + narch_flags) == 0){
error("unknown architecture specification flag: "
"%s %s", argv[i], argv[i+1]);
arch_usage();
usage();
}
narch_flags++;
}
i++;
continue;
}
if(argv[i][1] == 'p'){
if(argc <= i + 1){
error("-p requires an argument (a text symbol name)");
usage();
}
if(pflag)
error("only one -p flag can be specified");
pflag = argv[i + 1];
i++;
continue;
}
if(argv[i][1] == 's'){
if(argc <= i + 2){
error("-s requires two arguments (a segment name and a "
"section name)");
usage();
}
if(sectname != NULL){
error("only one -s flag can be specified");
usage();
}
segname = argv[i + 1];
sectname = argv[i + 2];
i += 2;
object_processing = TRUE;
continue;
}
for(j = 1; argv[i][j] != '\0'; j++){
switch(argv[i][j]){
case 'V':
Vflag = TRUE;
case 'v':
vflag = TRUE;
break;
case 'f':
fflag = TRUE;
break;
case 'a':
aflag = TRUE;
break;
case 'h':
hflag = TRUE;
object_processing = TRUE;
break;
case 'l':
lflag = TRUE;
object_processing = TRUE;
break;
case 'L':
Lflag = TRUE;
object_processing = TRUE;
break;
case 'D':
Dflag = TRUE;
object_processing = TRUE;
break;
case 't':
tflag = TRUE;
object_processing = TRUE;
break;
case 'd':
dflag = TRUE;
object_processing = TRUE;
break;
case 'o':
oflag = TRUE;
object_processing = TRUE;
break;
case 'O':
Oflag = TRUE;
object_processing = TRUE;
break;
case 'r':
rflag = TRUE;
object_processing = TRUE;
break;
case 'T':
Tflag = TRUE;
object_processing = TRUE;
break;
case 'M':
Mflag = TRUE;
object_processing = TRUE;
break;
case 'R':
Rflag = TRUE;
object_processing = TRUE;
break;
case 'I':
Iflag = TRUE;
object_processing = TRUE;
break;
case 'H':
Hflag = TRUE;
object_processing = TRUE;
break;
case 'S':
Sflag = TRUE;
break;
case 'c':
cflag = TRUE;
object_processing = TRUE;
break;
case 'i':
iflag = TRUE;
object_processing = TRUE;
break;
case 'W':
Wflag = TRUE;
break;
case 'X':
Xflag = TRUE;
break;
case 'Z':
Zflag = TRUE;
break;
case 'm':
use_member_syntax = FALSE;
break;
default:
error("unknown char `%c' in flag %s\n", argv[i][j],argv[i]);
usage();
}
}
}
if(!fflag && !aflag && !hflag && !lflag && !Lflag && !tflag && !dflag &&
!oflag && !Oflag && !rflag && !Tflag && !Mflag && !Rflag && !Iflag &&
!Hflag && !Sflag && !cflag && !iflag && !Dflag && !segname){
error("one of -fahlLtdoOrTMRIHScis must be specified");
usage();
}
if(nfiles == 0){
error("at least one file must be specified");
usage();
}
if(segname != NULL && sectname != NULL){
if(strcmp(segname, SEG_TEXT) == 0 &&
strcmp(sectname, SECT_TEXT) == 0){
tflag = TRUE;
segname = NULL;
sectname = NULL;
}
else if(strcmp(segname, SEG_TEXT) == 0 &&
strcmp(sectname, SECT_FVMLIB_INIT0) == 0){
iflag = TRUE;
segname = NULL;
sectname = NULL;
}
}
for(j = 0; j < nfiles; j++){
ofile_process(files[j], arch_flags, narch_flags, all_archs, TRUE,
TRUE, use_member_syntax, processor, NULL);
}
if(errors)
return(EXIT_FAILURE);
else
return(EXIT_SUCCESS);
}
static
void
usage(
void)
{
fprintf(stderr,
"Usage: %s [-fahlLDtdorSTMRIHvVcXm] <object file> ...\n",
progname);
fprintf(stderr, "\t-f print the fat headers\n");
fprintf(stderr, "\t-a print the archive header\n");
fprintf(stderr, "\t-h print the mach header\n");
fprintf(stderr, "\t-l print the load commands\n");
fprintf(stderr, "\t-L print shared libraries used\n");
fprintf(stderr, "\t-D print shared library id name\n");
fprintf(stderr, "\t-t print the text section (disassemble with -v)\n");
fprintf(stderr, "\t-p <routine name> start dissassemble from routine "
"name\n");
fprintf(stderr, "\t-s <segname> <sectname> print contents of "
"section\n");
fprintf(stderr, "\t-d print the data section\n");
fprintf(stderr, "\t-o print the Objective-C segment\n");
fprintf(stderr, "\t-r print the relocation entries\n");
fprintf(stderr, "\t-S print the table of contents of a library\n");
fprintf(stderr, "\t-T print the table of contents of a dynamic "
"shared library\n");
fprintf(stderr, "\t-M print the module table of a dynamic shared "
"library\n");
fprintf(stderr, "\t-R print the reference table of a dynamic shared "
"library\n");
fprintf(stderr, "\t-I print the indirect symbol table\n");
fprintf(stderr, "\t-H print the two-level hints table\n");
fprintf(stderr, "\t-v print verbosely (symbolicly) when possible\n");
fprintf(stderr, "\t-V print disassembled operands symbolicly\n");
fprintf(stderr, "\t-c print argument strings of a core file\n");
fprintf(stderr, "\t-X print no leading addresses or headers\n");
fprintf(stderr, "\t-m don't use archive(member) syntax\n");
exit(EXIT_FAILURE);
}
static
void
processor(
struct ofile *ofile,
char *arch_name,
void *cookie)
{
char *addr;
unsigned long i, size, magic;
struct mach_header mh;
struct load_command *load_commands;
unsigned long nsymbols, nsorted_symbols, strings_size, len;
struct nlist *symbols, *allocated_symbols, *sorted_symbols;
char *strings, *p;
unsigned char n_type;
char *sect;
unsigned long sect_size, sect_addr, sect_nrelocs, sect_flags, nrelocs;
struct relocation_info *sect_relocs, *relocs;
unsigned long *indirect_symbols, *allocated_indirect_symbols,
nindirect_symbols;
struct dylib_module *mods, *allocated_mods;
struct dylib_table_of_contents *tocs, *allocated_tocs;
struct dylib_reference *refs, *allocated_refs;
unsigned long nmods, ntocs, nrefs;
struct twolevel_hint *hints, *allocated_hints;
unsigned long nhints;
sorted_symbols = NULL;
nsorted_symbols = 0;
indirect_symbols = NULL;
nindirect_symbols = 0;
hints = NULL;
nhints = 0;
load_commands = NULL;
allocated_symbols = NULL;
sorted_symbols = NULL;
allocated_indirect_symbols = NULL;
allocated_tocs = NULL;
allocated_mods = NULL;
allocated_refs = NULL;
allocated_hints = NULL;
if(aflag && ofile->member_ar_hdr != NULL)
print_ar_hdr(ofile->member_ar_hdr, ofile->member_name,
ofile->member_name_size, vflag);
if(ofile->member_ar_hdr != NULL &&
strncmp(ofile->member_name, SYMDEF, sizeof(SYMDEF)-1) == 0){
if(Sflag == FALSE)
return;
if(ofile->file_type == OFILE_FAT){
addr = ofile->file_addr + ofile->fat_archs[ofile->narch].offset;
size = ofile->fat_archs[ofile->narch].size;
}
else{
addr = ofile->file_addr;
size = ofile->file_size;
}
if(addr + size > ofile->file_addr + ofile->file_size)
size = (ofile->file_addr + ofile->file_size) - addr;
print_library_toc(ofile->member_ar_hdr,
ofile->member_name,
ofile->member_name_size,
ofile->member_addr,
ofile->member_size,
get_toc_byte_sex(addr, size),
ofile->file_name,
addr,
size,
arch_name,
vflag);
return;
}
if(object_processing == FALSE)
return;
if(Xflag == FALSE){
printf("%s", ofile->file_name);
if(ofile->member_ar_hdr != NULL){
printf("(%.*s)", (int)ofile->member_name_size,
ofile->member_name);
}
if(arch_name != NULL)
printf(" (architecture %s):", arch_name);
else
printf(":");
if(ofile->mh == NULL){
if(ofile->file_type == OFILE_FAT){
if(ofile->arch_type == OFILE_ARCHIVE){
addr = ofile->member_addr;
size = ofile->member_size;
}
else{
addr = ofile->file_addr +
ofile->fat_archs[ofile->narch].offset;
size = ofile->fat_archs[ofile->narch].size;
}
if(addr + size > ofile->file_addr + ofile->file_size)
size = (ofile->file_addr + ofile->file_size) - addr;
}
else if(ofile->file_type == OFILE_ARCHIVE){
addr = ofile->member_addr;
size = ofile->member_size;
}
else{
addr = ofile->file_addr;
size = ofile->file_size;
}
if(size > sizeof(long)){
memcpy(&magic, addr, sizeof(unsigned long));
if(magic == MH_MAGIC || magic == SWAP_LONG(MH_MAGIC)){
printf(" is a truncated object file\n");
memset(&mh, '\0', sizeof(struct mach_header));
if(size > sizeof(struct mach_header))
size = sizeof(struct mach_header);
memcpy(&mh, addr, size);
if(magic == SWAP_LONG(MH_MAGIC))
swap_mach_header(&mh, get_host_byte_sex());
if(hflag)
print_mach_header(&mh, vflag);
return;
}
}
printf(" is not an object file\n");
return;
}
}
if(ofile->mh != NULL){
if((int)(ofile->mh) % sizeof(unsigned long)){
if(Xflag == FALSE)
printf("(object file offset is not a multiple of sizeof("
"unsigned long))");
memcpy(&mh, ofile->mh, sizeof(struct mach_header));
if(mh.magic == SWAP_LONG(MH_MAGIC))
swap_mach_header(&mh, get_host_byte_sex());
ofile->mh = &mh;
}
else if(ofile->mh->magic == SWAP_LONG(MH_MAGIC)){
mh = *(ofile->mh);
swap_mach_header(&mh, get_host_byte_sex());
ofile->mh = &mh;
}
}
if(Xflag == FALSE)
printf("\n");
if(ofile->mh == NULL)
return;
addr = ofile->object_addr;
size = ofile->object_size;
if(addr + size > ofile->file_addr + ofile->file_size)
size = (ofile->file_addr + ofile->file_size) - addr;
if(hflag)
print_mach_header(ofile->mh, vflag);
if(ofile->mh->sizeofcmds + sizeof(struct mach_header) > size){
load_commands = allocate(ofile->mh->sizeofcmds);
memset(load_commands, '\0', ofile->mh->sizeofcmds);
memcpy(load_commands, ofile->load_commands,
size - sizeof(struct mach_header));
ofile->load_commands = load_commands;
}
if(lflag)
print_loadcmds(ofile->mh, ofile->load_commands,
ofile->object_byte_sex, size, vflag, Vflag);
if(Lflag || Dflag)
print_libraries(ofile->mh, ofile->load_commands,
ofile->object_byte_sex, (Dflag && !Lflag), vflag);
sect_flags = 0;
if(segname != NULL && sectname != NULL){
(void)get_sect_info(segname, sectname, ofile->mh,
ofile->load_commands, ofile->object_byte_sex,
addr, size, §, §_size, §_addr,
§_relocs, §_nrelocs, §_flags);
if(ofile->mh->filetype == MH_DYLIB_STUB &&
((sect_flags & SECTION_TYPE) == S_NON_LAZY_SYMBOL_POINTERS ||
(sect_flags & SECTION_TYPE) == S_LAZY_SYMBOL_POINTERS ||
(sect_flags & SECTION_TYPE) == S_SYMBOL_STUBS))
sect_size = 0;
}
if(Rflag || Mflag)
get_symbol_table_info(ofile->mh, ofile->load_commands,
ofile->object_byte_sex, addr, size,
&symbols, &nsymbols, &strings, &strings_size);
if(vflag && (rflag || Tflag || Mflag || Rflag || Iflag || Hflag || tflag
|| iflag || oflag ||
(sect_flags & SECTION_TYPE) == S_LITERAL_POINTERS ||
(sect_flags & S_ATTR_PURE_INSTRUCTIONS) ==
S_ATTR_PURE_INSTRUCTIONS ||
(sect_flags & S_ATTR_SOME_INSTRUCTIONS) ==
S_ATTR_SOME_INSTRUCTIONS)){
get_symbol_table_info(ofile->mh, ofile->load_commands,
ofile->object_byte_sex, addr, size,
&symbols, &nsymbols, &strings, &strings_size);
if((int)symbols % sizeof(unsigned long) ||
ofile->object_byte_sex != get_host_byte_sex()){
allocated_symbols = allocate(nsymbols * sizeof(struct nlist));
memcpy(allocated_symbols, symbols,
nsymbols * sizeof(struct nlist));
symbols = allocated_symbols;
}
if(ofile->object_byte_sex != get_host_byte_sex())
swap_nlist(symbols, nsymbols, get_host_byte_sex());
if(tflag || iflag || oflag ||
(sect_flags & S_ATTR_PURE_INSTRUCTIONS) ==
S_ATTR_PURE_INSTRUCTIONS ||
(sect_flags & S_ATTR_SOME_INSTRUCTIONS) ==
S_ATTR_SOME_INSTRUCTIONS){
sorted_symbols = allocate(nsymbols * sizeof(struct nlist));
nsorted_symbols = 0;
for(i = 0; i < nsymbols; i++){
if(symbols[i].n_un.n_strx > 0 &&
(unsigned long)symbols[i].n_un.n_strx < strings_size)
p = strings + symbols[i].n_un.n_strx;
else
p = "symbol with bad string index";
if(symbols[i].n_type & ~(N_TYPE|N_EXT|N_PEXT))
continue;
n_type = symbols[i].n_type & N_TYPE;
if(n_type == N_ABS || n_type == N_SECT){
len = strlen(p);
if(len > sizeof(".o") - 1 &&
strcmp(p + (len - (sizeof(".o") - 1)), ".o") == 0)
continue;
if(strcmp(p, "gcc_compiled.") == 0)
continue;
if(n_type == N_ABS && symbols[i].n_value == 0 &&
*p == '.')
continue;
sorted_symbols[nsorted_symbols] = symbols[i];
sorted_symbols[nsorted_symbols].n_un.n_name = p;
nsorted_symbols++;
}
}
qsort(sorted_symbols, nsorted_symbols, sizeof(struct nlist),
(int (*)(const void *, const void *))sym_compare);
}
}
if(Mflag || Tflag || Rflag){
get_module_table_info(ofile->mh, ofile->load_commands,
ofile->object_byte_sex, addr, size, &mods, &nmods);
if((int)mods % sizeof(unsigned long) ||
ofile->object_byte_sex != get_host_byte_sex()){
allocated_mods = allocate(nmods * sizeof(struct dylib_module));
memcpy(allocated_mods, mods,
nmods * sizeof(struct dylib_module));
mods = allocated_mods;
}
if(ofile->object_byte_sex != get_host_byte_sex())
swap_dylib_module(mods, nmods, get_host_byte_sex());
}
if(Tflag){
get_toc_info(ofile->mh, ofile->load_commands,
ofile->object_byte_sex, addr, size, &tocs, &ntocs);
if((int)tocs % sizeof(unsigned long) ||
ofile->object_byte_sex != get_host_byte_sex()){
allocated_tocs = allocate(ntocs *
sizeof(struct dylib_table_of_contents));
memcpy(allocated_tocs, tocs,
ntocs * sizeof(struct dylib_table_of_contents));
tocs = allocated_tocs;
}
if(ofile->object_byte_sex != get_host_byte_sex())
swap_dylib_table_of_contents(tocs, ntocs, get_host_byte_sex());
print_toc(ofile->mh, ofile->load_commands,
ofile->object_byte_sex, addr, size, tocs, ntocs, mods, nmods,
symbols, nsymbols, strings, strings_size, vflag);
}
if(Mflag)
print_module_table(ofile->mh, ofile->load_commands,
ofile->object_byte_sex, addr, size, mods, nmods,
symbols, nsymbols, strings, strings_size, vflag);
if(Rflag){
get_ref_info(ofile->mh, ofile->load_commands,
ofile->object_byte_sex, addr, size, &refs, &nrefs);
if((int)refs % sizeof(unsigned long) ||
ofile->object_byte_sex != get_host_byte_sex()){
allocated_refs = allocate(nrefs *
sizeof(struct dylib_reference));
memcpy(allocated_refs, refs,
nrefs * sizeof(struct dylib_reference));
refs = allocated_refs;
}
if(ofile->object_byte_sex != get_host_byte_sex())
swap_dylib_reference(refs, nrefs, get_host_byte_sex());
print_refs(ofile->mh, ofile->load_commands,
ofile->object_byte_sex, addr, size, refs, nrefs, mods, nmods,
symbols, nsymbols, strings, strings_size, vflag);
}
if(Iflag || (tflag && vflag)){
get_indirect_symbol_table_info(ofile->mh, ofile->load_commands,
ofile->object_byte_sex, addr, size,
&indirect_symbols, &nindirect_symbols);
if((int)indirect_symbols % sizeof(unsigned long) ||
ofile->object_byte_sex != get_host_byte_sex()){
allocated_indirect_symbols = allocate(nindirect_symbols *
sizeof(unsigned long));
memcpy(allocated_indirect_symbols, indirect_symbols,
nindirect_symbols * sizeof(unsigned long));
indirect_symbols = allocated_indirect_symbols;
}
if(ofile->object_byte_sex != get_host_byte_sex())
swap_indirect_symbols(indirect_symbols, nindirect_symbols,
get_host_byte_sex());
}
if(Hflag){
get_hints_table_info(ofile->mh, ofile->load_commands,
ofile->object_byte_sex, addr, size,
&hints, &nhints);
if((int)hints % sizeof(unsigned long) ||
ofile->object_byte_sex != get_host_byte_sex()){
allocated_hints = allocate(nhints *
sizeof(struct twolevel_hint));
memcpy(allocated_hints, hints,
nhints * sizeof(struct twolevel_hint));
hints = allocated_hints;
}
if(ofile->object_byte_sex != get_host_byte_sex())
swap_twolevel_hint(hints, nhints, get_host_byte_sex());
print_hints(ofile->mh, ofile->load_commands,
ofile->object_byte_sex, addr, size, hints,
nhints, symbols, nsymbols, strings, strings_size, vflag);
}
if(Iflag)
print_indirect_symbols(ofile->mh, ofile->load_commands,
ofile->object_byte_sex, addr, size, indirect_symbols,
nindirect_symbols, symbols, nsymbols, strings, strings_size,
vflag);
if(rflag)
print_reloc(ofile->mh, ofile->load_commands, ofile->object_byte_sex,
addr, size, symbols, nsymbols, strings, strings_size,
vflag);
if(tflag ||
(sect_flags & S_ATTR_PURE_INSTRUCTIONS) ==
S_ATTR_PURE_INSTRUCTIONS ||
(sect_flags & S_ATTR_SOME_INSTRUCTIONS) ==
S_ATTR_SOME_INSTRUCTIONS){
if(tflag)
(void)get_sect_info(SEG_TEXT, SECT_TEXT, ofile->mh,
ofile->load_commands, ofile->object_byte_sex,
addr, size, §, §_size, §_addr,
§_relocs, §_nrelocs, §_flags);
relocs = NULL;
nrelocs = 0;
if(Vflag){
if((long)sect_relocs % sizeof(long) != 0 ||
ofile->object_byte_sex != get_host_byte_sex()){
nrelocs = sect_nrelocs;
relocs = allocate(nrelocs *
sizeof(struct relocation_info));
memcpy(relocs, sect_relocs, nrelocs *
sizeof(struct relocation_info));
}
else{
nrelocs = sect_nrelocs;
relocs = sect_relocs;
}
if(ofile->object_byte_sex != get_host_byte_sex())
swap_relocation_info(relocs, nrelocs,
get_host_byte_sex());
}
if(Xflag == FALSE){
if(tflag)
printf("(%s,%s) section\n", SEG_TEXT, SECT_TEXT);
else
printf("Contents of (%.16s,%.16s) section\n", segname,
sectname);
}
print_text(ofile->mh->cputype, ofile->object_byte_sex,
sect, sect_size, sect_addr, sorted_symbols,
nsorted_symbols, symbols, nsymbols, strings,
strings_size, relocs, nrelocs,
indirect_symbols, nindirect_symbols, ofile->mh, ofile->load_commands,
vflag, Vflag);
if(relocs != NULL && relocs != sect_relocs)
free(relocs);
}
if(iflag){
if(get_sect_info(SEG_TEXT, SECT_FVMLIB_INIT0, ofile->mh,
ofile->load_commands, ofile->object_byte_sex,
addr, size, §, §_size, §_addr,
§_relocs, §_nrelocs, §_flags) == TRUE){
nrelocs = sect_nrelocs;
relocs = allocate(nrelocs * sizeof(struct relocation_info));
memcpy(relocs, sect_relocs, nrelocs *
sizeof(struct relocation_info));
if(ofile->object_byte_sex != get_host_byte_sex())
swap_relocation_info(relocs, nrelocs, get_host_byte_sex());
qsort(relocs, nrelocs, sizeof(struct relocation_info),
(int (*)(const void *, const void *))rel_compare);
if(Xflag == FALSE)
printf("Shared library initialization (%s,%s) section\n",
SEG_TEXT, SECT_FVMLIB_INIT0);
print_shlib_init(ofile->object_byte_sex, sect, sect_size,
sect_addr, sorted_symbols, nsorted_symbols, symbols,
nsymbols, strings, strings_size, relocs, nrelocs,vflag);
free(relocs);
}
}
if(dflag){
if(get_sect_info(SEG_DATA, SECT_DATA, ofile->mh,
ofile->load_commands, ofile->object_byte_sex,
addr, size, §, §_size, §_addr,
§_relocs, §_nrelocs, §_flags) == TRUE){
if(Xflag == FALSE)
printf("(%s,%s) section\n", SEG_DATA, SECT_DATA);
print_sect(ofile->mh->cputype, ofile->object_byte_sex,
sect, sect_size, sect_addr);
}
}
if(segname != NULL && sectname != NULL &&
(sect_flags & S_ATTR_PURE_INSTRUCTIONS) !=
S_ATTR_PURE_INSTRUCTIONS &&
(sect_flags & S_ATTR_SOME_INSTRUCTIONS) !=
S_ATTR_SOME_INSTRUCTIONS){
if(strcmp(segname, SEG_OBJC) == 0 &&
strcmp(sectname, "__protocol") == 0 && vflag == TRUE){
print_objc_protocol_section(ofile->mh, ofile->load_commands,
ofile->object_byte_sex, ofile->object_addr,
ofile->object_size, vflag);
}
else if(strcmp(segname, SEG_OBJC) == 0 &&
(strcmp(sectname, "__string_object") == 0 ||
strcmp(sectname, "__cstring_object") == 0) &&
vflag == TRUE){
print_objc_string_object_section(sectname, ofile->mh,
ofile->load_commands, ofile->object_byte_sex,
ofile->object_addr, ofile->object_size, vflag);
}
else if(strcmp(segname, SEG_OBJC) == 0 &&
strcmp(sectname, "__runtime_setup") == 0 && vflag == TRUE){
print_objc_runtime_setup_section(ofile->mh,ofile->load_commands,
ofile->object_byte_sex, ofile->object_addr,
ofile->object_size, vflag);
}
else if(get_sect_info(segname, sectname, ofile->mh,
ofile->load_commands, ofile->object_byte_sex,
addr, size, §, §_size, §_addr,
§_relocs, §_nrelocs, §_flags) == TRUE){
if(Xflag == FALSE)
printf("Contents of (%.16s,%.16s) section\n", segname,
sectname);
if(vflag){
switch((sect_flags & SECTION_TYPE)){
case 0:
print_sect(ofile->mh->cputype, ofile->object_byte_sex,
sect, sect_size, sect_addr);
break;
case S_ZEROFILL:
printf("zerofill section and has no contents in the "
"file\n");
break;
case S_CSTRING_LITERALS:
print_cstring_section(sect, sect_size, sect_addr,
Xflag == TRUE ? FALSE : TRUE);
break;
case S_4BYTE_LITERALS:
print_literal4_section(sect, sect_size, sect_addr,
ofile->object_byte_sex,
Xflag == TRUE ? FALSE : TRUE);
break;
case S_8BYTE_LITERALS:
print_literal8_section(sect, sect_size, sect_addr,
ofile->object_byte_sex,
Xflag == TRUE ? FALSE : TRUE);
break;
case S_LITERAL_POINTERS:
nrelocs = sect_nrelocs;
relocs = allocate(nrelocs *
sizeof(struct relocation_info));
memcpy(relocs, sect_relocs, nrelocs *
sizeof(struct relocation_info));
if(ofile->object_byte_sex != get_host_byte_sex())
swap_relocation_info(relocs, nrelocs,
get_host_byte_sex());
qsort(relocs, nrelocs, sizeof(struct relocation_info),
(int (*)(const void *, const void *))rel_compare);
print_literal_pointer_section(ofile->mh,
ofile->load_commands, ofile->object_byte_sex,
addr, size, sect, sect_size, sect_addr,
symbols, nsymbols, strings, strings_size,
relocs, nrelocs, Xflag == TRUE ? FALSE : TRUE);
free(relocs);
break;
default:
printf("Unknown section type (0x%x)\n",
(unsigned int)(sect_flags & SECTION_TYPE));
print_sect(ofile->mh->cputype, ofile->object_byte_sex,
sect, sect_size, sect_addr);
break;
}
}
else{
if((sect_flags & SECTION_TYPE) == S_ZEROFILL)
printf("zerofill section and has no contents in the "
"file\n");
else
print_sect(ofile->mh->cputype, ofile->object_byte_sex,
sect, sect_size, sect_addr);
}
}
}
if(cflag)
print_argstrings(ofile->mh, ofile->load_commands,
ofile->object_byte_sex, ofile->object_addr,
ofile->object_size);
if(oflag)
print_objc_segment(ofile->mh, ofile->load_commands,
ofile->object_byte_sex, ofile->object_addr,
ofile->object_size, sorted_symbols,
nsorted_symbols, vflag);
if(load_commands != NULL)
free(load_commands);
if(allocated_symbols != NULL)
free(allocated_symbols);
if(sorted_symbols != NULL)
free(sorted_symbols);
if(allocated_indirect_symbols != NULL)
free(allocated_indirect_symbols);
if(allocated_hints != NULL)
free(allocated_hints);
if(allocated_tocs != NULL)
free(allocated_tocs);
if(allocated_mods != NULL)
free(allocated_mods);
if(allocated_refs != NULL)
free(allocated_refs);
}
static
void
get_symbol_table_info(
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex load_commands_byte_sex,
char *object_addr,
unsigned long object_size,
struct nlist **symbols,
unsigned long *nsymbols,
char **strings,
unsigned long *strings_size)
{
enum byte_sex host_byte_sex;
enum bool swapped;
unsigned long i, left, size, st_cmd;
struct load_command *lc, l;
struct symtab_command st;
*symbols = NULL;
*nsymbols = 0;
*strings = NULL;
*strings_size = 0;
host_byte_sex = get_host_byte_sex();
swapped = host_byte_sex != load_commands_byte_sex;
st_cmd = ULONG_MAX;
lc = load_commands;
for(i = 0 ; i < mh->ncmds; i++){
memcpy((char *)&l, (char *)lc, sizeof(struct load_command));
if(swapped)
swap_load_command(&l, host_byte_sex);
if(l.cmdsize % sizeof(long) != 0)
printf("load command %lu size not a multiple of "
"sizeof(long)\n", i);
if((char *)lc + l.cmdsize >
(char *)load_commands + mh->sizeofcmds)
printf("load command %lu extends past end of load "
"commands\n", i);
left = mh->sizeofcmds - ((char *)lc - (char *)load_commands);
switch(l.cmd){
case LC_SYMTAB:
if(st_cmd != ULONG_MAX){
printf("more than one LC_SYMTAB command (using command %lu)"
"\n", st_cmd);
break;
}
memset((char *)&st, '\0', sizeof(struct symtab_command));
size = left < sizeof(struct symtab_command) ?
left : sizeof(struct symtab_command);
memcpy((char *)&st, (char *)lc, size);
if(swapped)
swap_symtab_command(&st, host_byte_sex);
st_cmd = i;
}
if(l.cmdsize == 0){
printf("load command %lu size zero (can't advance to other "
"load commands)\n", i);
break;
}
lc = (struct load_command *)((char *)lc + l.cmdsize);
if((char *)lc > (char *)load_commands + mh->sizeofcmds)
break;
}
if((char *)load_commands + mh->sizeofcmds != (char *)lc)
printf("Inconsistent mh_sizeofcmds\n");
if(st_cmd == ULONG_MAX){
return;
}
if(st.symoff >= object_size){
printf("symbol table offset is past end of file\n");
}
else{
*symbols = (struct nlist *)(object_addr + st.symoff);
if(st.symoff + st.nsyms * sizeof(struct nlist) > object_size){
printf("symbol table extends past end of file\n");
*nsymbols = (object_size - st.symoff) / sizeof(struct nlist);
}
else
*nsymbols = st.nsyms;
}
if(st.stroff >= object_size){
printf("string table offset is past end of file\n");
}
else{
*strings = object_addr + st.stroff;
if(st.stroff + st.strsize > object_size){
printf("string table extends past end of file\n");
*strings_size = object_size - st.symoff;
}
else
*strings_size = st.strsize;
}
}
static
void
get_toc_info(
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex load_commands_byte_sex,
char *object_addr,
unsigned long object_size,
struct dylib_table_of_contents **tocs,
unsigned long *ntocs)
{
struct dysymtab_command dyst;
*tocs = NULL;
*ntocs = 0;
if(get_dyst(mh, load_commands, load_commands_byte_sex, &dyst) == FALSE)
return;
if(dyst.tocoff >= object_size){
printf("table of contents offset is past end of file\n");
}
else{
*tocs = (struct dylib_table_of_contents *)(object_addr +
dyst.tocoff);
if(dyst.tocoff + dyst.ntoc *
sizeof(struct dylib_table_of_contents) > object_size){
printf("table of contents extends past end of file\n");
*ntocs = (object_size - dyst.tocoff) /
sizeof(struct dylib_table_of_contents);
}
else
*ntocs = dyst.ntoc;
}
}
static
void
get_module_table_info(
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex load_commands_byte_sex,
char *object_addr,
unsigned long object_size,
struct dylib_module **mods,
unsigned long *nmods)
{
struct dysymtab_command dyst;
*mods = NULL;
*nmods = 0;
if(get_dyst(mh, load_commands, load_commands_byte_sex, &dyst) == FALSE)
return;
if(dyst.modtaboff >= object_size){
printf("module table offset is past end of file\n");
}
else{
*mods = (struct dylib_module *)(object_addr + dyst.modtaboff);
if(dyst.modtaboff +
dyst.nmodtab * sizeof(struct dylib_module) > object_size){
printf("module table extends past end of file\n");
*nmods = (object_size - dyst.modtaboff) /
sizeof(struct dylib_module);
}
else
*nmods = dyst.nmodtab;
}
}
static
void
get_ref_info(
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex load_commands_byte_sex,
char *object_addr,
unsigned long object_size,
struct dylib_reference **refs,
unsigned long *nrefs)
{
struct dysymtab_command dyst;
*refs = NULL;
*nrefs = 0;
if(get_dyst(mh, load_commands, load_commands_byte_sex, &dyst) == FALSE)
return;
if(dyst.extrefsymoff >= object_size){
printf("reference table offset is past end of file\n");
}
else{
*refs = (struct dylib_reference *)(object_addr + dyst.extrefsymoff);
if(dyst.extrefsymoff + dyst.nextrefsyms *
sizeof(struct dylib_reference) > object_size){
printf("reference table extends past end of file\n");
*nrefs = (object_size - dyst.extrefsymoff) /
sizeof(struct dylib_reference);
}
else
*nrefs = dyst.nextrefsyms;
}
}
static
void
get_indirect_symbol_table_info(
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex load_commands_byte_sex,
char *object_addr,
unsigned long object_size,
unsigned long **indirect_symbols,
unsigned long *nindirect_symbols)
{
struct dysymtab_command dyst;
*indirect_symbols = NULL;
*nindirect_symbols = 0;
if(get_dyst(mh, load_commands, load_commands_byte_sex, &dyst) == FALSE)
return;
if(dyst.indirectsymoff >= object_size){
printf("indirect symbol table offset is past end of file\n");
}
else{
*indirect_symbols = (unsigned long *)(object_addr +
dyst.indirectsymoff);
if(dyst.indirectsymoff +
dyst.nindirectsyms * sizeof(unsigned long) > object_size){
printf("indirect symbol table extends past end of file\n");
*nindirect_symbols = (object_size - dyst.indirectsymoff) /
sizeof(unsigned long);
}
else
*nindirect_symbols = dyst.nindirectsyms;
}
}
static
enum bool
get_dyst(
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex load_commands_byte_sex,
struct dysymtab_command *dyst)
{
enum byte_sex host_byte_sex;
enum bool swapped;
unsigned long i, left, size, dyst_cmd;
struct load_command *lc, l;
host_byte_sex = get_host_byte_sex();
swapped = host_byte_sex != load_commands_byte_sex;
dyst_cmd = ULONG_MAX;
lc = load_commands;
for(i = 0 ; i < mh->ncmds; i++){
memcpy((char *)&l, (char *)lc, sizeof(struct load_command));
if(swapped)
swap_load_command(&l, host_byte_sex);
if(l.cmdsize % sizeof(long) != 0)
printf("load command %lu size not a multiple of "
"sizeof(long)\n", i);
if((char *)lc + l.cmdsize >
(char *)load_commands + mh->sizeofcmds)
printf("load command %lu extends past end of load "
"commands\n", i);
left = mh->sizeofcmds - ((char *)lc - (char *)load_commands);
switch(l.cmd){
case LC_DYSYMTAB:
if(dyst_cmd != ULONG_MAX){
printf("more than one LC_DYSYMTAB command (using command "
"%lu)\n", dyst_cmd);
break;
}
memset((char *)dyst, '\0', sizeof(struct dysymtab_command));
size = left < sizeof(struct dysymtab_command) ?
left : sizeof(struct dysymtab_command);
memcpy((char *)dyst, (char *)lc, size);
if(swapped)
swap_dysymtab_command(dyst, host_byte_sex);
dyst_cmd = i;
}
if(l.cmdsize == 0){
printf("load command %lu size zero (can't advance to other "
"load commands)\n", i);
break;
}
lc = (struct load_command *)((char *)lc + l.cmdsize);
if((char *)lc > (char *)load_commands + mh->sizeofcmds)
break;
}
if((char *)load_commands + mh->sizeofcmds != (char *)lc)
printf("Inconsistent mh_sizeofcmds\n");
if(dyst_cmd == ULONG_MAX){
return(FALSE);
}
return(TRUE);
}
static
void
get_hints_table_info(
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex load_commands_byte_sex,
char *object_addr,
unsigned long object_size,
struct twolevel_hint **hints,
unsigned long *nhints)
{
struct twolevel_hints_command hints_cmd;
*hints = NULL;
*nhints = 0;
if(get_hints_cmd(mh, load_commands, load_commands_byte_sex,
&hints_cmd) == FALSE)
return;
if(hints_cmd.offset >= object_size){
printf("two-level hints offset is past end of file\n");
}
else{
*hints = (struct twolevel_hint *)(object_addr + hints_cmd.offset);
if(hints_cmd.offset +
hints_cmd.nhints * sizeof(struct twolevel_hint) > object_size){
printf("two-level hints table extends past end of file\n");
*nhints = (object_size - hints_cmd.offset) /
sizeof(struct twolevel_hint);
}
else
*nhints = hints_cmd.nhints;
}
}
static
enum bool
get_hints_cmd(
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex load_commands_byte_sex,
struct twolevel_hints_command *hints_cmd)
{
enum byte_sex host_byte_sex;
enum bool swapped;
unsigned long i, left, size, cmd;
struct load_command *lc, l;
host_byte_sex = get_host_byte_sex();
swapped = host_byte_sex != load_commands_byte_sex;
cmd = ULONG_MAX;
lc = load_commands;
for(i = 0 ; i < mh->ncmds; i++){
memcpy((char *)&l, (char *)lc, sizeof(struct load_command));
if(swapped)
swap_load_command(&l, host_byte_sex);
if(l.cmdsize % sizeof(long) != 0)
printf("load command %lu size not a multiple of "
"sizeof(long)\n", i);
if((char *)lc + l.cmdsize >
(char *)load_commands + mh->sizeofcmds)
printf("load command %lu extends past end of load "
"commands\n", i);
left = mh->sizeofcmds - ((char *)lc - (char *)load_commands);
switch(l.cmd){
case LC_TWOLEVEL_HINTS:
if(cmd != ULONG_MAX){
printf("more than one LC_TWOLEVEL_HINTS command (using "
"command %lu)\n", cmd);
break;
}
memset((char *)hints_cmd, '\0',
sizeof(struct twolevel_hints_command));
size = left < sizeof(struct twolevel_hints_command) ?
left : sizeof(struct twolevel_hints_command);
memcpy((char *)hints_cmd, (char *)lc, size);
if(swapped)
swap_twolevel_hints_command(hints_cmd, host_byte_sex);
cmd = i;
}
if(l.cmdsize == 0){
printf("load command %lu size zero (can't advance to other "
"load commands)\n", i);
break;
}
lc = (struct load_command *)((char *)lc + l.cmdsize);
if((char *)lc > (char *)load_commands + mh->sizeofcmds)
break;
}
if((char *)load_commands + mh->sizeofcmds != (char *)lc)
printf("Inconsistent mh_sizeofcmds\n");
if(cmd == ULONG_MAX){
return(FALSE);
}
return(TRUE);
}
static
int
sym_compare(
struct nlist *sym1,
struct nlist *sym2)
{
if(sym1->n_value == sym2->n_value)
return(0);
if(sym1->n_value < sym2->n_value)
return(-1);
else
return(1);
}
static
int
rel_compare(
struct relocation_info *rel1,
struct relocation_info *rel2)
{
struct scattered_relocation_info *srel;
unsigned long r_address1, r_address2;
if((rel1->r_address & R_SCATTERED) != 0){
srel = (struct scattered_relocation_info *)rel1;
r_address1 = srel->r_address;
}
else
r_address1 = rel1->r_address;
if((rel2->r_address & R_SCATTERED) != 0){
srel = (struct scattered_relocation_info *)rel2;
r_address2 = srel->r_address;
}
else
r_address2 = rel2->r_address;
if(r_address1 == r_address2)
return(0);
if(r_address1 < r_address2)
return(-1);
else
return(1);
}
static
enum bool
get_sect_info(
char *segname,
char *sectname,
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex load_commands_byte_sex,
char *object_addr,
unsigned long object_size,
char **sect_pointer,
unsigned long *sect_size,
unsigned long *sect_addr,
struct relocation_info **sect_relocs,
unsigned long *sect_nrelocs,
unsigned long *sect_flags)
{
enum byte_sex host_byte_sex;
enum bool found, swapped;
unsigned long i, j, left, size;
struct load_command *lc, l;
struct segment_command sg;
struct section s;
char *p;
*sect_pointer = NULL;
*sect_size = 0;
*sect_addr = 0;
*sect_relocs = NULL;
*sect_nrelocs = 0;
*sect_flags = 0;
found = FALSE;
host_byte_sex = get_host_byte_sex();
swapped = host_byte_sex != load_commands_byte_sex;
lc = load_commands;
for(i = 0 ; found == FALSE && i < mh->ncmds; i++){
memcpy((char *)&l, (char *)lc, sizeof(struct load_command));
if(swapped)
swap_load_command(&l, host_byte_sex);
if(l.cmdsize % sizeof(long) != 0)
printf("load command %lu size not a multiple of "
"sizeof(long)\n", i);
if((char *)lc + l.cmdsize >
(char *)load_commands + mh->sizeofcmds)
printf("load command %lu extends past end of load "
"commands\n", i);
left = mh->sizeofcmds - ((char *)lc - (char *)load_commands);
switch(l.cmd){
case LC_SEGMENT:
memset((char *)&sg, '\0', sizeof(struct segment_command));
size = left < sizeof(struct segment_command) ?
left : sizeof(struct segment_command);
memcpy((char *)&sg, (char *)lc, size);
if(swapped)
swap_segment_command(&sg, host_byte_sex);
if((mh->filetype == MH_OBJECT && sg.segname[0] == '\0') ||
strncmp(sg.segname, segname, sizeof(sg.segname)) == 0){
p = (char *)lc + sizeof(struct segment_command);
for(j = 0 ; found == FALSE && j < sg.nsects ; j++){
if(p + sizeof(struct section) >
(char *)load_commands + mh->sizeofcmds){
printf("section structure command extends past "
"end of load commands\n");
}
left = mh->sizeofcmds - (p - (char *)load_commands);
memset((char *)&s, '\0', sizeof(struct section));
size = left < sizeof(struct section) ?
left : sizeof(struct section);
memcpy((char *)&s, p, size);
if(swapped)
swap_section(&s, 1, host_byte_sex);
if(strncmp(s.sectname, sectname,
sizeof(s.sectname)) == 0 &&
strncmp(s.segname, segname,
sizeof(s.segname)) == 0){
found = TRUE;
break;
}
if(p + sizeof(struct section) >
(char *)load_commands + mh->sizeofcmds)
return(FALSE);
p += size;
}
}
break;
}
if(l.cmdsize == 0){
printf("load command %lu size zero (can't advance to other "
"load commands)\n", i);
break;
}
lc = (struct load_command *)((char *)lc + l.cmdsize);
if((char *)lc > (char *)load_commands + mh->sizeofcmds)
break;
}
if(found == FALSE)
return(FALSE);
if((s.flags & SECTION_TYPE) == S_ZEROFILL){
*sect_pointer = NULL;
*sect_size = s.size;
}
else{
if(s.offset >= object_size){
printf("section offset for section (%.16s,%.16s) is past end "
"of file\n", s.segname, s.sectname);
}
else{
*sect_pointer = object_addr + s.offset;
if(s.offset + s.size > object_size){
printf("section (%.16s,%.16s) extends past end of file\n",
s.segname, s.sectname);
*sect_size = object_size - s.offset;
}
else
*sect_size = s.size;
}
}
if(s.reloff >= object_size){
printf("relocation entries offset for (%.16s,%.16s): is past end "
"of file\n", s.segname, s.sectname);
}
else{
*sect_relocs = (struct relocation_info *)(object_addr + s.reloff);
if(s.reloff + s.nreloc * sizeof(struct relocation_info) >
object_size){
printf("relocation entries for section (%.16s,%.16s) extends "
"past end of file\n", s.segname, s.sectname);
*sect_nrelocs = (object_size - s.reloff) /
sizeof(struct relocation_info);
}
else
*sect_nrelocs = s.nreloc;
}
*sect_addr = s.addr;
*sect_flags = s.flags;
return(TRUE);
}
static
void
print_text(
cpu_type_t cputype,
enum byte_sex object_byte_sex,
char *sect,
unsigned long size,
unsigned long addr,
struct nlist *sorted_symbols,
unsigned long nsorted_symbols,
struct nlist *symbols,
unsigned long nsymbols,
char *strings,
unsigned long strings_size,
struct relocation_info *relocs,
unsigned long nrelocs,
unsigned long *indirect_symbols,
unsigned long nindirect_symbols,
struct mach_header *mh,
struct load_command *load_commands,
enum bool disassemble,
enum bool verbose)
{
enum byte_sex host_byte_sex;
enum bool swapped;
unsigned long i, j, offset, cur_addr, long_word;
unsigned short short_word;
unsigned char byte_word;
host_byte_sex = get_host_byte_sex();
swapped = host_byte_sex != object_byte_sex;
if(disassemble == TRUE){
if(pflag){
for(i = 0; i < nsorted_symbols; i++){
if(strcmp(sorted_symbols[i].n_un.n_name, pflag) == 0)
break;
}
if(i == nsorted_symbols){
printf("Can't find -p symbol: %s\n", pflag);
return;
}
if(sorted_symbols[i].n_value < addr ||
sorted_symbols[i].n_value >= addr + size){
printf("-p symbol: %s not in text section\n", pflag);
return;
}
offset = sorted_symbols[i].n_value - addr;
sect += offset;
cur_addr = sorted_symbols[i].n_value;
}
else{
offset = 0;
cur_addr = addr;
}
for(i = offset ; i < size ; ){
print_label(cur_addr, TRUE, sorted_symbols, nsorted_symbols);
if(Xflag)
printf("\t");
else
printf("%08x\t", (unsigned int)cur_addr);
if(cputype == CPU_TYPE_MC680x0)
j = m68k_disassemble(sect, size - i, cur_addr, addr,
object_byte_sex, relocs, nrelocs, symbols,
nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, indirect_symbols,
nindirect_symbols, mh, load_commands, verbose);
else if(cputype == CPU_TYPE_I860)
j = i860_disassemble(sect, size - i, cur_addr, addr,
object_byte_sex, relocs, nrelocs, symbols,
nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
else if(cputype == CPU_TYPE_I386)
j = i386_disassemble(sect, size - i, cur_addr, addr,
object_byte_sex, relocs, nrelocs, symbols,
nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, indirect_symbols,
nindirect_symbols, mh, load_commands, verbose);
else if(cputype == CPU_TYPE_MC88000)
j = m88k_disassemble(sect, size - i, cur_addr, addr,
object_byte_sex, relocs, nrelocs, symbols,
nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
else if(cputype == CPU_TYPE_POWERPC ||
cputype == CPU_TYPE_VEO)
j = ppc_disassemble(sect, size - i, cur_addr, addr,
object_byte_sex, relocs, nrelocs, symbols,
nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, indirect_symbols,
nindirect_symbols, mh, load_commands, verbose);
else if(cputype == CPU_TYPE_HPPA)
j = hppa_disassemble(sect, size - i, cur_addr, addr,
object_byte_sex, relocs, nrelocs, symbols,
nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
else if(cputype == CPU_TYPE_SPARC)
j = sparc_disassemble(sect, size - i, cur_addr, addr,
object_byte_sex, relocs, nrelocs, symbols,
nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, indirect_symbols,
nindirect_symbols, mh, load_commands, verbose);
else{
printf("Can't disassemble unknown cputype %d\n", cputype);
return;
}
sect += j;
cur_addr += j;
i += j;
}
}
else{
if(cputype == CPU_TYPE_I386){
for(i = 0 ; i < size ; i += j , addr += j){
printf("%08x ", (unsigned int)addr);
for(j = 0;
j < 16 * sizeof(char) && i + j < size;
j += sizeof(char)){
byte_word = *(sect + i + j);
printf("%02x ", (unsigned int)byte_word);
}
printf("\n");
}
}
else if(cputype == CPU_TYPE_MC680x0){
for(i = 0 ; i < size ; i += j , addr += j){
printf("%08x ", (unsigned int)addr);
for(j = 0;
j < 8 * sizeof(short) && i + j < size;
j += sizeof(short)){
memcpy(&short_word, sect + i + j, sizeof(short));
if(swapped)
short_word = SWAP_SHORT(short_word);
printf("%04x ", (unsigned int)short_word);
}
printf("\n");
}
}
else{
for(i = 0 ; i < size ; i += j , addr += j){
printf("%08x ", (unsigned int)addr);
for(j = 0;
j < 4 * sizeof(long) && i + j < size;
j += sizeof(long)){
memcpy(&long_word, sect + i + j, sizeof(long));
if(swapped)
long_word = SWAP_LONG(long_word);
printf("%08x ", (unsigned int)long_word);
}
printf("\n");
}
}
}
}
static
void
print_argstrings(
struct mach_header *mh,
struct load_command *load_commands,
enum byte_sex load_commands_byte_sex,
char *object_addr,
unsigned long object_size)
{
enum byte_sex host_byte_sex;
enum bool swapped;
unsigned long i, len, left, size, usrstack, arg;
struct load_command *lc, l;
struct segment_command sg;
char *stack, *stack_top, *p, *q, *argv;
struct arch_flag arch_flags;
host_byte_sex = get_host_byte_sex();
swapped = host_byte_sex != load_commands_byte_sex;
arch_flags.cputype = mh->cputype;
arch_flags.cpusubtype = mh->cpusubtype;
usrstack = get_stack_addr_from_flag(&arch_flags);
if(usrstack == 0){
printf("Don't know the value of USRSTACK for unknown cputype "
"(%d)\n", mh->cputype);
return;
}
printf("Argument strings on the stack at: 0x%x\n",
(unsigned int)usrstack);
lc = load_commands;
for(i = 0 ; i < mh->ncmds; i++){
memcpy((char *)&l, (char *)lc, sizeof(struct load_command));
if(swapped)
swap_load_command(&l, host_byte_sex);
if(l.cmdsize % sizeof(long) != 0)
printf("load command %lu size not a multiple of "
"sizeof(long)\n", i);
if((char *)lc + l.cmdsize >
(char *)load_commands + mh->sizeofcmds)
printf("load command %lu extends past end of load "
"commands\n", i);
left = mh->sizeofcmds - ((char *)lc - (char *)load_commands);
switch(l.cmd){
case LC_SEGMENT:
memset((char *)&sg, '\0', sizeof(struct segment_command));
size = left < sizeof(struct segment_command) ?
left : sizeof(struct segment_command);
memcpy((char *)&sg, (char *)lc, size);
if(swapped)
swap_segment_command(&sg, host_byte_sex);
if(mh->cputype == CPU_TYPE_HPPA){
if(sg.vmaddr == usrstack &&
sg.fileoff + sg.filesize <= object_size){
stack = object_addr + sg.fileoff;
stack_top = stack + sg.filesize;
argv = stack + 2 * sizeof(unsigned long);
memcpy(&arg, argv, sizeof(unsigned long));
if(swapped)
arg = SWAP_LONG(arg);
while(argv < stack_top &&
arg != 0 &&
arg >= usrstack && arg < usrstack + sg.filesize){
p = stack + (arg - usrstack);
printf("\t");
while(p < stack_top && *p != '\0'){
printf("%c", *p);
p++;
}
printf("\n");
argv += sizeof(unsigned long);
memcpy(&arg, argv, sizeof(unsigned long));
if(swapped)
arg = SWAP_LONG(arg);
}
argv += sizeof(unsigned long);
memcpy(&arg, argv, sizeof(unsigned long));
if(swapped)
arg = SWAP_LONG(arg);
while(argv < stack_top &&
arg != 0 &&
arg >= usrstack && arg < usrstack + sg.filesize){
p = stack + (arg - usrstack);
printf("\t");
while(p < stack_top && *p != '\0'){
printf("%c", *p);
p++;
}
printf("\n");
argv += sizeof(unsigned long);
memcpy(&arg, argv, sizeof(unsigned long));
if(swapped)
arg = SWAP_LONG(arg);
}
}
}
else{
if(sg.vmaddr + sg.vmsize == usrstack &&
sg.fileoff + sg.filesize <= object_size){
stack = object_addr + sg.fileoff;
stack_top = stack + sg.filesize;
stack_top -= 4;
p = (char *)stack_top;
while(p > stack && *p == '\0')
p--;
if(p != (char *)stack_top)
p++;
q = p;
while(p > stack && (*p != '\0' || *(p-1) != '\0' ||
*(p-2) != '\0' || *(p-3) != '\0')){
p--;
while(p > stack && *p != '\0')
p--;
}
p++;
while(p < q){
printf("\t");
len = 0;
while(p + len < q && p[len] != '\0'){
printf("%c", p[len]);
len++;
}
printf("\n");
p += len + 1;
}
return;
}
}
break;
}
if(l.cmdsize == 0){
printf("load command %lu size zero (can't advance to other "
"load commands)\n", i);
break;
}
lc = (struct load_command *)((char *)lc + l.cmdsize);
if((char *)lc > (char *)load_commands + mh->sizeofcmds)
break;
}
}
size_t hw_sqrt_len = 0;
double
sqrt(double x)
{
return(0.0);
}
double
hw_sqrt(double x)
{
return(0.0);
}
#ifdef __ppc__
long
__fpclassifyd(double x)
{
return(0);
}
#endif
#ifdef __i386__
long
__fpclassify(long double x)
{
return(0);
}
#endif