//-------------------------------------------------------------------------- const char *idaapi set_idp_options(const char *keyword,int /*value_type*/,const void * /*value*/) { if ( keyword != NULL ) return IDPOPT_BADKEY; if ( choose_ioport_device(cfgname, device, sizeof(device), NULL) ) load_symbols(); return IDPOPT_OK; }
struct ao_hex_image * ao_hex_load(char *filename, struct ao_sym **symbols, int *num_symbolsp) { FILE *file; struct ao_hex_file *hex_file; struct ao_hex_image *hex_image; file = fopen (filename, "r"); if (!file) return NULL; hex_file = ao_hex_file_read(file, filename); fclose(file); if (!hex_file) return NULL; hex_image = ao_hex_image_create(hex_file); if (!hex_image) return NULL; if (symbols) *symbols = load_symbols(hex_file, num_symbolsp); ao_hex_file_free(hex_file); return hex_image; }
void init_libretro_sym(bool dummy) { // Guarantee that we can do "dirty" casting. // Every OS that this program supports should pass this ... rarch_assert(sizeof(void*) == sizeof(void (*)(void))); if (!dummy) { #ifdef HAVE_DYNAMIC // Try to verify that -lretro was not linked in from other modules // since loading it dynamically and with -l will fail hard. function_t sym = dylib_proc(NULL, "retro_init"); if (sym) { RARCH_ERR("Serious problem. RetroArch wants to load libretro dyamically, but it is already linked.\n"); RARCH_ERR("This could happen if other modules RetroArch depends on link against libretro directly.\n"); RARCH_ERR("Proceeding could cause a crash. Aborting ...\n"); rarch_fail(1, "init_libretro_sym()"); } if (!*g_settings.libretro) { RARCH_ERR("RetroArch is built for dynamic libretro, but libretro_path is not set. Cannot continue.\n"); rarch_fail(1, "init_libretro_sym()"); } #endif } load_symbols(dummy); pretro_set_environment(environment_cb); }
//-------------------------------------------------------------------------- static void choose_device(TView *[],int) { if ( choose_ioport_device(cfgname, device, sizeof(device), NULL) ) { load_symbols(IORESP_ALL); apply_symbols(); } }
/** * init_libretro_sym: * @type : Type of core to be loaded. * If CORE_TYPE_DUMMY, will * load dummy symbols. * * Initializes libretro symbols and * setups environment callback functions. **/ void init_libretro_sym(enum rarch_core_type type) { /* Guarantee that we can do "dirty" casting. * Every OS that this program supports should pass this. */ retro_assert(sizeof(void*) == sizeof(void (*)(void))); load_symbols(type); }
void load_kernel_symbols(void *addr, uint32 num, uint32 size, uint32 shndx) { // These cryptic parameters are given to us by GRUB/multiboot. // From testing, they appear to be (all e_* values are from the ELF header) // addr: address of section header table (NOT address of ELF header!), // which is the ELF header's location + e_shoff // num: number of section headers, which is e_shnum // size: size of each entry, which is e_shentsize // shndx: the string table's index into the SHT, which is e_shstrndx const char *sym_string_table = NULL; #if ELF_DEBUG char *string_table = (char *)(string_table_hdr->sh_addr); printk("Sections:\n"); printk("Idx Name Size VMA LMA File off Align\n"); #endif Elf32_Sym *symhdr = NULL; uint32 num_syms = 0; for (uint32 i=1; i < num; i++) { // skip #0, which is always empty Elf32_Shdr *shdr = (Elf32_Shdr *)((uint32)addr + (size * i)); if (shdr->sh_type == SHT_SYMTAB) { symhdr = (Elf32_Sym *)shdr->sh_addr; num_syms = shdr->sh_size / shdr->sh_entsize; Elf32_Shdr *string_table_hdr = (Elf32_Shdr *)((uint32)addr + shdr->sh_link * size); sym_string_table = (char *)(string_table_hdr->sh_addr); if (symhdr == NULL) { panic("Unable to locate kernel symbols!"); } #ifndef ELF_DEBUG break; #endif } #if ELF_DEBUG char *name = (char *)&string_table[shdr->sh_name]; printk("%03d %12s %08x %08x %08x %08x %u\n", i, name, shdr->sh_size, shdr->sh_addr, shdr->sh_addr /* TODO: LMA */, shdr->sh_offset, shdr->sh_addralign); unsigned int f = shdr->sh_flags; printk(" "); if (shdr->sh_type != SHT_NOBITS) printk("CONTENTS, "); if ((f & SHF_ALLOC)) printk("ALLOC, "); if ((f & SHF_WRITE) == 0) printk("READONLY, "); if ((f & SHF_EXECINSTR)) printk("CODE\n"); else printk("DATA\n"); #endif } if (load_symbols(symhdr, sym_string_table, &kernel_syms, num_syms) != 0) panic("unable to load kernel symbols"); }
//-------------------------------------------------------------------------- static void f2mc_set_device_name(const char *dev, int _respect_info) { if ( dev != NULL ) { if ( dev != device ) qstrncpy(device, dev, sizeof(device)); helper.supset(0, dev); } load_symbols(_respect_info); }
static void load_gnomesu(void) { static gboolean init; if (init) return; init = TRUE; load_symbols("libgnomesu.so.0", "gnomesu_exec", &gnomesu_exec, NULL); }
/* * Functions executed when calling g_module_open() and g_module_close() */ const gchar * g_module_check_init (GModule *module) { if (! bdbsql_module) { bdbsql_module = find_sqlite_library ("libdb_sql-5"); if (! bdbsql_module) bdbsql_module = find_sqlite_library ("libdb_sql-6"); } if (bdbsql_module) load_symbols (bdbsql_module); if (! s3r) return _("Can't find libdb_sql-5." G_MODULE_SUFFIX " or libdb_sql-6." G_MODULE_SUFFIX "file, or any dependent library"); /*g_module_make_resident (module);*/ return NULL; }
//-------------------------------------------------------------------------- void load_file(linput_t *li, ushort /*neflag*/, const char * /*fileformatname*/) { header h; qlseek(li, 0); lread(li, &h, sizeof(h)); h.swap(); if ( ph.id != PLFM_HPPA ) set_processor_type("hppa", SETPROC_ALL|SETPROC_FATAL); inf.baseaddr = 0; load_aux_headers(li, h.aux_header_location, h.aux_header_size); load_spaces(li, h, h.space_location, h.space_total); load_subspaces(li, h, h.subspace_location, h.subspace_total); load_symbols(li, h, h.symbol_location, h.symbol_total); load_dl_header(li); create_filename_cmt(); ulong dp = h.presumed_dp; if ( dp == 0 ) { // 23 61 28 00 ldil ...., %dp // 37 7B 01 60 ldo 0xB0(%dp), %dp if ( ua_ana0(inf.startIP) && cmd.Op1.type == o_imm && cmd.Op2.type == o_reg ) { ulong v = cmd.Op1.value; if ( ua_ana0(cmd.ea+4) && cmd.Op1.type == o_displ ) dp = v + cmd.Op1.addr; } } if ( dp != 0 ) { netnode n; n.create("$ got"); n.altset(0, dp+1); } add_til("hpux"); }
int main() { graph_t * g = graph::read_graph<graph_t>(); int C = g->vex_count(); char symbols[128]; load_symbols(symbols, C); mx_t mx(C, C); load_operand_relation(mx); int values[128]; load_operand_values(values, C); std::cout << "rev polish: "; print_reverse_polish(g, mx, symbols); int v = evaluate(g, mx, symbols, values); std::cout << "value: " << v << '\n'; delete g; return 0; }
//-------------------------------------------------------------------------- static void choose_device(TView *[],int) { if ( choose_ioport_device(cfgname, device, sizeof(device), NULL) ) load_symbols(); }
static int notify(processor_t::idp_notify msgid, ...) { va_list va; va_start(va, msgid); // A well behaving processor module should call invoke_callbacks() // in his notify() function. If this function returns 0, then // the processor module should process the notification itself // Otherwise the code should be returned to the caller: int code = invoke_callbacks(HT_IDP, msgid, va); if ( code ) return code; switch ( msgid ) { case processor_t::init: helper.create("$ tms320c54"); { char buf[MAXSTR]; if ( helper.supval(0, buf, sizeof(buf)) > 0 ) set_device_name(buf); } inf.mf = 1; // MSB first break; case processor_t::term: free_ioports(ports, numports); default: break; case processor_t::newfile: // new file loaded { { SetDefaultRegisterValue(NULL, ARMS, 0); SetDefaultRegisterValue(NULL, CPL, 1); for (int i = DP; i <= rVds; i++) SetDefaultRegisterValue(NULL, i, 0); } static const char informations[] = { "AUTOHIDE REGISTRY\n" "Default values of flags and registers:\n" "\n" "ARMS bit = 0 (DSP mode operands).\n" "CPL bit = 1 (SP direct addressing mode).\n" "DP register = 0 (Data Page register)\n" "DPH register = 0 (High part of EXTENDED Data Page Register)\n" "PDP register = 0 (Peripheral Data Page register)\n" "\n" "You can change the register values by pressing Alt-G\n" "(Edit, Segments, Change segment register value)\n" }; info(informations); break; } case processor_t::oldfile: // old file loaded idpflags = (ushort)helper.altval(-1); break; case processor_t::closebase: case processor_t::savebase: helper.altset(-1, idpflags); helper.supset(0, device); break; case processor_t::newprc: // new processor type { ptype = ptypes[va_arg(va, int)]; switch ( ptype ) { case TMS320C55: break; default: error("interr: setprc"); break; } device[0] = '\0'; load_symbols(); } break; case processor_t::newasm: // new assembler type break; case processor_t::newseg: // new segment break; case processor_t::get_stkvar_scale_factor: return 2; } va_end(va); return 1; }
int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, struct image_info * info) { struct elfhdr elf_ex; struct elfhdr interp_elf_ex; struct exec interp_ex; int interpreter_fd = -1; /* avoid warning */ abi_ulong load_addr, load_bias; int load_addr_set = 0; unsigned int interpreter_type = INTERPRETER_NONE; unsigned char ibcs2_interpreter; int i; abi_ulong mapped_addr; struct elf_phdr * elf_ppnt; struct elf_phdr *elf_phdata; abi_ulong elf_bss, k, elf_brk; int retval; char * elf_interpreter; abi_ulong elf_entry, interp_load_addr = 0; int status; abi_ulong start_code, end_code, start_data, end_data; abi_ulong reloc_func_desc = 0; abi_ulong elf_stack; char passed_fileno[6]; ibcs2_interpreter = 0; status = 0; load_addr = 0; load_bias = 0; elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */ #ifdef BSWAP_NEEDED bswap_ehdr(&elf_ex); #endif /* First of all, some simple consistency checks */ if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) || (! elf_check_arch(elf_ex.e_machine))) { return -ENOEXEC; } bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p); bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p); bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p); if (!bprm->p) { retval = -E2BIG; } /* Now read in all of the header information */ elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum); if (elf_phdata == NULL) { return -ENOMEM; } retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET); if(retval > 0) { retval = read(bprm->fd, (char *) elf_phdata, elf_ex.e_phentsize * elf_ex.e_phnum); } if (retval < 0) { perror("load_elf_binary"); exit(-1); free (elf_phdata); return -errno; } #ifdef BSWAP_NEEDED elf_ppnt = elf_phdata; for (i=0; i<elf_ex.e_phnum; i++, elf_ppnt++) { bswap_phdr(elf_ppnt); } #endif elf_ppnt = elf_phdata; elf_bss = 0; elf_brk = 0; elf_stack = ~((abi_ulong)0UL); elf_interpreter = NULL; start_code = ~((abi_ulong)0UL); end_code = 0; start_data = 0; end_data = 0; interp_ex.a_info = 0; for(i=0;i < elf_ex.e_phnum; i++) { if (elf_ppnt->p_type == PT_INTERP) { if ( elf_interpreter != NULL ) { free (elf_phdata); free(elf_interpreter); close(bprm->fd); return -EINVAL; } /* This is the program interpreter used for * shared libraries - for now assume that this * is an a.out format binary */ elf_interpreter = (char *)malloc(elf_ppnt->p_filesz); if (elf_interpreter == NULL) { free (elf_phdata); close(bprm->fd); return -ENOMEM; } retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET); if(retval >= 0) { retval = read(bprm->fd, elf_interpreter, elf_ppnt->p_filesz); } if(retval < 0) { perror("load_elf_binary2"); exit(-1); } /* If the program interpreter is one of these two, then assume an iBCS2 image. Otherwise assume a native linux image. */ /* JRP - Need to add X86 lib dir stuff here... */ if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 || strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) { ibcs2_interpreter = 1; } #if 0 printf("Using ELF interpreter %s\n", elf_interpreter); #endif if (retval >= 0) { retval = open(path(elf_interpreter), O_RDONLY); if(retval >= 0) { interpreter_fd = retval; } else { perror(elf_interpreter); exit(-1); /* retval = -errno; */ } } if (retval >= 0) { retval = lseek(interpreter_fd, 0, SEEK_SET); if(retval >= 0) { retval = read(interpreter_fd,bprm->buf,128); } } if (retval >= 0) { interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */ interp_elf_ex=*((struct elfhdr *) bprm->buf); /* elf exec-header */ } if (retval < 0) { perror("load_elf_binary3"); exit(-1); free (elf_phdata); free(elf_interpreter); close(bprm->fd); return retval; } } elf_ppnt++; } /* Some simple consistency checks for the interpreter */ if (elf_interpreter){ interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT; /* Now figure out which format our binary is */ if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) && (N_MAGIC(interp_ex) != QMAGIC)) { interpreter_type = INTERPRETER_ELF; } if (interp_elf_ex.e_ident[0] != 0x7f || strncmp((char *)&interp_elf_ex.e_ident[1], "ELF",3) != 0) { interpreter_type &= ~INTERPRETER_ELF; } if (!interpreter_type) { free(elf_interpreter); free(elf_phdata); close(bprm->fd); return -ELIBBAD; } } /* OK, we are done with that, now set up the arg stuff, and then start this sucker up */ { char * passed_p; if (interpreter_type == INTERPRETER_AOUT) { snprintf(passed_fileno, sizeof(passed_fileno), "%d", bprm->fd); passed_p = passed_fileno; if (elf_interpreter) { bprm->p = copy_elf_strings(1,&passed_p,bprm->page,bprm->p); bprm->argc++; } } if (!bprm->p) { if (elf_interpreter) { free(elf_interpreter); } free (elf_phdata); close(bprm->fd); return -E2BIG; } } /* OK, This is the point of no return */ info->end_data = 0; info->end_code = 0; info->start_mmap = (abi_ulong)ELF_START_MMAP; info->mmap = 0; info->elf_flags = elf_ex.e_flags; elf_entry = (abi_ulong) elf_ex.e_entry; /* Do this so that we can load the interpreter, if need be. We will change some of these later */ info->rss = 0; bprm->p = setup_arg_pages(bprm->p, bprm, info); info->start_stack = bprm->p; /* Now we do a little grungy work by mmaping the ELF image into * the correct location in memory. At this point, we assume that * the image should be loaded at fixed address, not at a variable * address. */ for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) { int elf_prot = 0; int elf_flags = 0; abi_ulong error; if (elf_ppnt->p_type != PT_LOAD) continue; if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ; if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; elf_flags = MAP_PRIVATE | MAP_DENYWRITE; if (elf_ex.e_type == ET_EXEC || load_addr_set) { elf_flags |= MAP_FIXED; } else if (elf_ex.e_type == ET_DYN) { /* Try and get dynamic programs out of the way of the default mmap base, as well as whatever program they might try to exec. This is because the brk will follow the loader, and is not movable. */ /* NOTE: for qemu, we do a big mmap to get enough space without hardcoding any address */ error = target_mmap(0, ET_DYN_MAP_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0); if (error == -1) { perror("mmap"); exit(-1); } load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr); } error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr), (elf_ppnt->p_filesz + TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)), elf_prot, (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE), bprm->fd, (elf_ppnt->p_offset - TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr))); if (error == -1) { perror("mmap"); exit(-1); } #ifdef LOW_ELF_STACK if (TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack) elf_stack = TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr); #endif if (!load_addr_set) { load_addr_set = 1; load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset; if (elf_ex.e_type == ET_DYN) { load_bias += error - TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr); load_addr += load_bias; reloc_func_desc = load_bias; } } k = elf_ppnt->p_vaddr; if (k < start_code) start_code = k; if (start_data < k) start_data = k; k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz; if (k > elf_bss) elf_bss = k; if ((elf_ppnt->p_flags & PF_X) && end_code < k) end_code = k; if (end_data < k) end_data = k; k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz; if (k > elf_brk) elf_brk = k; } elf_entry += load_bias; elf_bss += load_bias; elf_brk += load_bias; start_code += load_bias; end_code += load_bias; start_data += load_bias; end_data += load_bias; if (elf_interpreter) { if (interpreter_type & 1) { elf_entry = load_aout_interp(&interp_ex, interpreter_fd); } else if (interpreter_type & 2) { elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd, &interp_load_addr); } reloc_func_desc = interp_load_addr; close(interpreter_fd); free(elf_interpreter); if (elf_entry == ~((abi_ulong)0UL)) { printf("Unable to load interpreter\n"); free(elf_phdata); exit(-1); return 0; } } free(elf_phdata); if (loglevel) load_symbols(&elf_ex, bprm->fd); if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd); info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX); #ifdef LOW_ELF_STACK info->start_stack = bprm->p = elf_stack - 4; #endif bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &elf_ex, load_addr, load_bias, interp_load_addr, (interpreter_type == INTERPRETER_AOUT ? 0 : 1), info); info->load_addr = reloc_func_desc; info->start_brk = info->brk = elf_brk; info->end_code = end_code; info->start_code = start_code; info->start_data = start_data; info->end_data = end_data; info->start_stack = bprm->p; /* Calling set_brk effectively mmaps the pages that we need for the bss and break sections */ set_brk(elf_bss, elf_brk); padzero(elf_bss, elf_brk); #if 0 printf("(start_brk) %x\n" , info->start_brk); printf("(end_code) %x\n" , info->end_code); printf("(start_code) %x\n" , info->start_code); printf("(end_data) %x\n" , info->end_data); printf("(start_stack) %x\n" , info->start_stack); printf("(brk) %x\n" , info->brk); #endif if ( info->personality == PER_SVR4 ) { /* Why this, you ask??? Well SVr4 maps page 0 as read-only, and some applications "depend" upon this behavior. Since we do not have the power to recompile these, we emulate the SVr4 behavior. Sigh. */ mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, -1, 0); } info->entry = elf_entry; return 0; }
static int idaapi notify(processor_t::idp_notify msgid, ...) { va_list va; va_start(va, msgid); // A well behaving processor module should call invoke_callbacks() // in his notify() function. If this function returns 0, then // the processor module should process the notification itself // Otherwise the code should be returned to the caller: int code = invoke_callbacks(HT_IDP, msgid, va); if ( code ) return code; switch ( msgid ) { case processor_t::init: helper.create("$ st20"); helper.supval(0, device, sizeof(device)); break; case processor_t::term: free_ioports(ports, numports); default: break; case processor_t::newfile: // new file loaded case processor_t::oldfile: // old file loaded load_symbols(); break; case processor_t::savebase: case processor_t::closebase: helper.supset(0, device); break; case processor_t::newprc: // new processor type procnum = va_arg(va, int); if ( isc4() ) ph.retcodes = retcodes4; break; case processor_t::is_jump_func: { const func_t *pfn = va_arg(va, const func_t *); ea_t *jump_target = va_arg(va, ea_t *); return is_jump_func(pfn, jump_target); } case processor_t::is_sane_insn: return is_sane_insn(va_arg(va, int)); case processor_t::may_be_func: // can a function start here? // arg: none, the instruction is in 'cmd' // returns: probability 0..100 // 'cmd' structure is filled upon the entrace // the idp module is allowed to modify 'cmd' return may_be_func(); } va_end(va); return 1; }
static int elf_load_int(const char *path, task_t *task, char *argv[], char *envp[]) { // Loads to a fixed address of 0x10000000 for now; not a HUGE deal // since each (user mode) task has its own address space assert(interrupts_enabled() == false); // TODO: get rid of the race condition from create_task, so that this isn't needed assert(task != NULL); struct task_mm *mm = task->mm; assert(mm != NULL); struct stat st; int r; if ((r = stat(path, &st)) != 0) { assert(r < 0); return r; } uint32 file_size = st.st_size; unsigned char *data = kmalloc(file_size); int retval = 0; int fd = open(path, O_RDONLY); if (fd < 0) { printk("elf_load(): unable to open %s\n", path); retval = fd; goto err; } if ((r = read(fd, data, file_size)) != (int)file_size) { printk("elf_load(): unable to read from %s; got %d bytes, requested %d\n", path, r, (int)file_size); if (r < 0) { retval = r; goto err; } else { panic("read() returned less than the expected file size, but not a negative value... why?"); retval = -EIO; goto err; } } close(fd); elf_header_t *header = (elf_header_t *)data; const unsigned char ELF_IDENT[] = {0x7f, 'E', 'L', 'F'}; if (memcmp(header->e_ident.ei_mag, &ELF_IDENT, 4) != 0) { printk("Warning: file %s is not an ELF file; aborting execution\n", path); retval = -ENOEXEC; goto err; } // TODO SECURITY: don't trust anything from the file - users can EASILY execute // "forged" ELF files! if (header->e_ident.ei_class != ELFCLASS32 || header->e_ident.ei_data != ELFDATA2LSB || \ header->e_ident.ei_version != 1 || header->e_machine != EM_386 || header->e_type != ET_EXEC) { printk("Warning: file %s is not a valid ELF file (invalid ELFCLASS, ELFDATA, version, machine or not ET_EXEC\n"); retval = -ENOEXEC; goto err; } assert(header->e_entry >= 0x10000000); assert(header->e_entry < 0x11000000); if (task == current_task) { // execve assert(current_task->mm != NULL); assert(current_task->mm->areas != NULL); assert(current_task->mm->page_directory != NULL); } for (int i=0; i < header->e_phnum; i++) { Elf32_Phdr *phdr = (Elf32_Phdr *)(data + header->e_phoff + header->e_phentsize * i); if (phdr->p_type == PT_LOAD) { // This is a segment to load! // Should this be writable to the task? bool writable = ((phdr->p_flags & PF_W) ? true : false); #if ELF_DEBUG printk("Segment #%u: copy %u bytes from 0x%08x (data + offset) to 0x%08x (virt in task page dir); read%s\n", i, phdr->p_filesz, data + phdr->p_offset, phdr->p_vaddr, writable ? "-write" : "only"); #endif if (i == 0) assert(phdr->p_vaddr == 0x10000000); else assert(phdr->p_vaddr > 0x10000000); uint32 start_addr = phdr->p_vaddr; uint32 start_addr_aligned = (phdr->p_vaddr & 0xfffff000); uint32 end_addr = start_addr + phdr->p_memsz; if (!IS_PAGE_ALIGNED(end_addr)) { end_addr &= ~(PAGE_SIZE - 1); end_addr += PAGE_SIZE; } if (end_addr > task->mm->brk_start) { uint32 new_brk = end_addr; if (!IS_PAGE_ALIGNED(new_brk)) { new_brk &= ~(PAGE_SIZE - 1); new_brk += PAGE_SIZE; } task->mm->brk_start = new_brk; task->mm->brk = new_brk; } // Allocate memory for this address in the task's address space, set for user mode vmm_alloc_user(start_addr_aligned, end_addr, mm, writable); // Switch to the new page directory, so that we can copy the data there page_directory_t *old_dir = current_directory; switch_page_directory(mm->page_directory); // Okay, we should have the memory. Let's clear it (since PARTS may be left empty by the memcpy, // e.g. the .bss section, and we do want zeroes to be there) memset((void *)start_addr_aligned, 0, end_addr - start_addr_aligned); // Copy the segment (e.g. .text + .rodata + .eh_frame, or .data + .bss) to the location // DO NOT use start_addr_aligned here - we want the program to dictate the exact location memcpy((void *)start_addr, data + phdr->p_offset, phdr->p_filesz); switch_page_directory(old_dir); } else if (phdr->p_type == PT_GNU_STACK || phdr->p_type == PT_GNU_RELRO || phdr->p_type == PT_GNU_EH_FRAME) { // Quietly ignore } else printk("Warning: skipping unsupported ELF program header (#%u, p_type = 0x%x)\n", i, phdr->p_type); } // Set up the reentrancy structure for Newlib // (It is initialized below, after switching to the new page directory.) uint32 reent_size = sizeof(struct _reent); if (reent_size & 0xfff) { reent_size &= 0xfffff000; reent_size += PAGE_SIZE; } vmm_alloc_user(task->mm->brk, task->mm->brk + reent_size, mm, PAGE_RW); //assert(current_directory == kernel_directory); page_directory_t *old_dir = current_directory; switch_page_directory(task->mm->page_directory); task->reent = (struct _reent *)task->mm->brk; _REENT_INIT_PTR(task->reent); task->mm->brk += reent_size; task->mm->brk_start += reent_size; assert(IS_PAGE_ALIGNED(task->mm->brk)); assert(task->mm->brk == task->mm->brk_start); // The value brk has when the process starts; // userspace may not decrease the brk point below this address task->mm->initial_brk = task->mm->brk_start; // Copy the argv data from the kernel heap to the task's address space // This function updates argv to point to the new location. uint32 argc = 0; for (; argv[argc] != NULL; argc++) { } copy_argv_env_to_task(&argv, argc, task); uint32 envc = 0; assert(envp != NULL); for (; envp[envc] != NULL; envc++) { } copy_argv_env_to_task(&envp, envc, task); *((uint32 *)(USER_STACK_START - 0)) = (uint32)envp; *((uint32 *)(USER_STACK_START - 4)) = (uint32)argv; *((uint32 *)(USER_STACK_START - 8)) = (uint32)argc; // Update the task's name strlcpy((char *)task->name, argv[0], TASK_NAME_LEN); if (old_dir != kernel_directory) { // execve, stay with the new dir } else switch_page_directory(old_dir); #if ELF_DEBUG printk("File has %u program headers (each %u bytes), %u section headers (each %u bytes)\n", header->e_phnum, header->e_phentsize, header->e_shnum, header->e_shentsize); printk("Program Header:\n"); for (int i=0; i < header->e_phnum; i++) { Elf32_Phdr *phdr = (Elf32_Phdr *)(data + header->e_phoff + header->e_phentsize * i); if (phdr->p_type == PT_LOAD) { printk("LOAD offset 0x%08x vaddr 0x%08x alignment %u bytes\n", phdr->p_offset, phdr->p_vaddr, phdr->p_align); unsigned int f = phdr->p_flags; printk(" filesz 0x%08x memsz 0x%08x flags %c%c%c\n", phdr->p_filesz, phdr->p_memsz, (f & PF_R ? 'r' : '-'), (f & PF_W ? 'w' : '-'), (f & PF_X ? 'x' : '-')); } else { printk("unsupported program header (#%u), skipping\n", i); } } // Find the string table assert(header->e_shoff != 0); // we need a section header Elf32_Shdr *string_table_hdr = (Elf32_Shdr *)(data + header->e_shoff + header->e_shentsize * header->e_shstrndx); char *string_table = (char *)(data + string_table_hdr->sh_offset); printk("Sections:\n"); printk("Idx Name Size VMA LMA File off Align\n"); for (int i=1; i < header->e_shnum; i++) { // skip #0, which is always empty Elf32_Shdr *shdr = (Elf32_Shdr *)(data + header->e_shoff + header->e_shentsize * i); char *name = (char *)&string_table[shdr->sh_name]; printk("%03d %12s %08x %08x %08x %08x %u\n", i, name, shdr->sh_size, shdr->sh_addr, shdr->sh_addr /* TODO: LMA */, shdr->sh_offset, shdr->sh_addralign); unsigned int f = shdr->sh_flags; printk(" "); if (shdr->sh_type != SHT_NOBITS) printk("CONTENTS, "); if ((f & SHF_ALLOC)) printk("ALLOC, "); if ((f & SHF_WRITE) == 0) printk("READONLY, "); if ((f & SHF_EXECINSTR)) printk("CODE\n"); else printk("DATA\n"); } #endif // ELF_DEBUG // Try to find symbols, so we can get nice backtrace displays Elf32_Sym *symhdr = NULL; uint32 num_syms = 0; const char *sym_string_table = NULL; uint32 string_table_size = 0; for (uint32 i=1; i < header->e_shnum; i++) { // skip #0, which is always empty Elf32_Shdr *shdr = (Elf32_Shdr *)((uint32)data + header->e_shoff + (header->e_shentsize * i)); if (shdr->sh_type == SHT_SYMTAB) { symhdr = (Elf32_Sym *)(data + shdr->sh_offset); num_syms = shdr->sh_size / shdr->sh_entsize; Elf32_Shdr *string_table_hdr = (Elf32_Shdr *)((uint32)data + header->e_shoff + shdr->sh_link * header->e_shentsize); string_table_size = string_table_hdr->sh_size; sym_string_table = (char *)(data + string_table_hdr->sh_offset); break; } } // Load symbols for this file, so that we can display them in backtraces if (!symhdr || !sym_string_table || num_syms < 1) { printk("Warning: failed to load symbols for %s\n", path); } else { // Clone the string table. Because load_symbols doesn't strdup() names // for performance reasons, we need the string table to keep existing // for as long as the task lives. char *old_table = task->symbol_string_table; task->symbol_string_table = kmalloc(string_table_size); task->symbol_string_table_size = string_table_size; memcpy(task->symbol_string_table, sym_string_table, string_table_size); if (load_symbols(symhdr, task->symbol_string_table, &task->symbols, num_syms) != 0) { printk("Warning: failed to load symbols for %s\n", path); } else if (old_table) { // execve, so free the old one, or it'll leak kfree(old_table); } } // If we're still here: set the program entry point // (This updates the value on the stack in task.c) task->new_entry = (uint32)header->e_entry; set_entry_point((task_t *)task, task->new_entry); retval = 0; /* fall through on success */ err: kfree(data); assert(retval <= 0); return retval; }
int om_oracle8i_init(int argc, char **argv, struct filed *f, char *prog, void **c, char **status) { struct om_oracle8i_ctx *ctx; char buf[1024]; char err_buf[512]; int err; if (argv == NULL || *argv == NULL || argc < 2 || f == NULL || c == NULL || *c != NULL) return (-1); m_dprintf(MSYSLOG_INFORMATIVE, "om_oracle8i_init: alloc context\n"); if ((*c = (void *)calloc(1, sizeof (struct om_oracle8i_ctx))) == NULL) return (-1); ctx = (struct om_oracle8i_ctx *)*c; if (1 != load_symbols(ctx)) { free(ctx); return -1; } if (1 != parse_arguments(ctx, argc, argv)) { goto om_oracle8i_init_bad; } err = ctx->OCIEnvCreate(&ctx->env, OCI_DEFAULT, NULL, NULL, NULL, NULL, 0, NULL); if (OCI_SUCCESS != err) { ctx->OCIErrorGet(ctx->env, 1, NULL, &err, err_buf, sizeof err_buf, OCI_HTYPE_ENV); snprintf(buf, sizeof buf, "om_oracle8i_init: Error " "initializing handle [%s]", err_buf); logerror(buf); goto om_oracle8i_init_bad; } ctx->OCIHandleAlloc(ctx->env, &ctx->err, OCI_HTYPE_ERROR, 0, NULL); m_dprintf(MSYSLOG_INFORMATIVE, "om_oracle8i_init: params %p %s %s \n", ctx->env, ctx->user, ctx->db); if (1 != prepare_query(ctx)) { goto om_oracle8i_init_bad; } snprintf(buf, sizeof (buf), "om_oracle8i: sending " "messages to database %s, table %s.", ctx->db, ctx->table); *status = strdup(buf); /* Connect to the database. */ err = ctx->OCILogon(ctx->env, ctx->err, &ctx->svc, ctx->user, strlen(ctx->user), ctx->passwd, strlen(ctx->passwd), ctx->db, strlen(ctx->db)); if (OCI_SUCCESS != err) { ctx->OCIErrorGet(ctx->err, 1, NULL, &err, err_buf, sizeof err_buf, OCI_HTYPE_ERROR); snprintf(buf, sizeof buf, "om_oracle8i_init: Error " "connecting to db server [%s] user [%s] db [%s]", err_buf, ctx->user, ctx->db); logerror(buf); /* Another Logon operation will be tried when needed. */ } else { ctx->loggedon = 1; } return (1); om_oracle8i_init_bad: if (ctx) { om_oracle8i_close(f, ctx); free(ctx); *c = NULL; } *status = NULL; return (-1); }
int main(int argc, char *argv[]) { const char *errstr; char errbuf[_POSIX2_LINE_MAX], *kmem = NULL, *kernel = NULL; struct kinfo_proc *kproc; struct sum total_sum; int many, ch, rc; kvm_t *kd; pid_t pid = -1; gid_t gid; while ((ch = getopt(argc, argv, "AaD:dlmM:N:p:Prsvx")) != -1) { switch (ch) { case 'A': print_amap = 1; break; case 'a': print_all = 1; break; case 'd': print_ddb = 1; break; case 'D': debug = strtonum(optarg, 0, 0xf, &errstr); if (errstr) errx(1, "invalid debug mask"); break; case 'l': print_maps = 1; break; case 'm': print_map = 1; break; case 'M': kmem = optarg; break; case 'N': kernel = optarg; break; case 'p': pid = strtopid(optarg); break; case 'P': pid = getpid(); break; case 's': print_solaris = 1; break; case 'v': verbose = 1; break; case 'r': case 'x': errx(1, "-%c option not implemented, sorry", ch); /*NOTREACHED*/ default: usage(); } } /* * Discard setgid privileges if not the running kernel so that bad * guys can't print interesting stuff from kernel memory. */ gid = getgid(); if (kernel != NULL || kmem != NULL) if (setresgid(gid, gid, gid) == -1) err(1, "setresgid"); argc -= optind; argv += optind; /* more than one "process" to dump? */ many = (argc > 1 - (pid == -1 ? 0 : 1)) ? 1 : 0; /* apply default */ if (print_all + print_map + print_maps + print_solaris + print_ddb == 0) print_solaris = 1; /* start by opening libkvm */ kd = kvm_openfiles(kernel, kmem, NULL, O_RDONLY, errbuf); if (kernel == NULL && kmem == NULL) if (setresgid(gid, gid, gid) == -1) err(1, "setresgid"); if (kd == NULL) errx(1, "%s", errbuf); /* get "bootstrap" addresses from kernel */ load_symbols(kd); memset(&total_sum, 0, sizeof(total_sum)); do { struct sum sum; memset(&sum, 0, sizeof(sum)); if (pid == -1) { if (argc == 0) pid = getppid(); else { pid = strtopid(argv[0]); argv++; argc--; } } /* find the process id */ if (pid == 0) kproc = NULL; else { kproc = kvm_getprocs(kd, KERN_PROC_PID, pid, sizeof(struct kinfo_proc), &rc); if (kproc == NULL || rc == 0) { warnc(ESRCH, "%d", pid); pid = -1; continue; } } /* dump it */ if (many) { if (kproc) printf("process %d:\n", pid); else printf("kernel:\n"); } process_map(kd, pid, kproc, &sum); if (print_amap) print_sum(&sum, &total_sum); pid = -1; } while (argc > 0); if (print_amap) print_sum(&total_sum, NULL); /* done. go away. */ rc = kvm_close(kd); if (rc == -1) err(1, "kvm_close"); return (0); }
static int notify(processor_t::idp_notify msgid, ...) { va_list va; va_start(va, msgid); // A well behaving processor module should call invoke_callbacks() // in his notify() function. If this function returns 0, then // the processor module should process the notification itself // Otherwise the code should be returned to the caller: int code = invoke_callbacks(HT_IDP, msgid, va); if ( code ) return code; switch ( msgid ) { case processor_t::init: // __emit__(0xCC); // debugger trap helper.create("$ h8/500"); inf.mf = 1; default: break; case processor_t::term: free_syms(); break; case processor_t::oldfile: // old file loaded idpflags = ushort(helper.altval(-1) + 1); create_segment_registers(); // no break case processor_t::newfile: // new file loaded load_symbols("h8500.cfg"); inf.mf = 1; break; case processor_t::closebase: case processor_t::savebase: helper.altset(-1, idpflags - 1); break; case processor_t::newseg: // new segment { segment_t *sptr = va_arg(va, segment_t *); sptr->defsr[BR-ph.regFirstSreg] = 0; sptr->defsr[DP-ph.regFirstSreg] = 0; } break; case processor_t::is_jump_func: { const func_t *pfn = va_arg(va, const func_t *); ea_t *jump_target = va_arg(va, ea_t *); return is_jump_func(pfn, jump_target); } case processor_t::is_sane_insn: return is_sane_insn(va_arg(va, int)); case processor_t::may_be_func: // can a function start here? // arg: none, the instruction is in 'cmd' // returns: probability 0..100 // 'cmd' structure is filled upon the entrace // the idp module is allowed to modify 'cmd' return may_be_func(); } va_end(va); return 1; }
/* NOTE: all the constants are the HOST ones */ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, int flags, int fd, abi_ulong offset) { abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len; unsigned long host_start; mmap_lock(); #ifdef DEBUG_MMAP { printf("mmap: start=0x" TARGET_ABI_FMT_lx " len=0x" TARGET_ABI_FMT_lx " prot=%c%c%c flags=", start, len, prot & PROT_READ ? 'r' : '-', prot & PROT_WRITE ? 'w' : '-', prot & PROT_EXEC ? 'x' : '-'); if (flags & MAP_FIXED) printf("MAP_FIXED "); if (flags & MAP_ANONYMOUS) printf("MAP_ANON "); switch(flags & MAP_TYPE) { case MAP_PRIVATE: printf("MAP_PRIVATE "); break; case MAP_SHARED: printf("MAP_SHARED "); break; default: printf("[MAP_TYPE=0x%x] ", flags & MAP_TYPE); break; } printf("fd=%d offset=" TARGET_ABI_FMT_lx "\n", fd, offset); } #endif if (offset & ~TARGET_PAGE_MASK) { errno = EINVAL; goto fail; } len = TARGET_PAGE_ALIGN(len); if (len == 0) goto the_end; real_start = start & qemu_host_page_mask; /* When mapping files into a memory area larger than the file, accesses to pages beyond the file size will cause a SIGBUS. For example, if mmaping a file of 100 bytes on a host with 4K pages emulating a target with 8K pages, the target expects to be able to access the first 8K. But the host will trap us on any access beyond 4K. When emulating a target with a larger page-size than the hosts, we may need to truncate file maps at EOF and add extra anonymous pages up to the targets page boundary. */ if ((qemu_real_host_page_size < TARGET_PAGE_SIZE) && !(flags & MAP_ANONYMOUS)) { struct stat sb; if (fstat (fd, &sb) == -1) goto fail; /* Are we trying to create a map beyond EOF?. */ if (offset + len > sb.st_size) { /* If so, truncate the file map at eof aligned with the hosts real pagesize. Additional anonymous maps will be created beyond EOF. */ len = (sb.st_size - offset); len += qemu_real_host_page_size - 1; len &= ~(qemu_real_host_page_size - 1); } } if (!(flags & MAP_FIXED)) { abi_ulong mmap_start; void *p; host_offset = offset & qemu_host_page_mask; host_len = len + offset - host_offset; host_len = HOST_PAGE_ALIGN(host_len); mmap_start = mmap_find_vma(real_start, host_len); if (mmap_start == (abi_ulong)-1) { errno = ENOMEM; goto fail; } /* Note: we prefer to control the mapping address. It is especially important if qemu_host_page_size > qemu_real_host_page_size */ p = mmap(g2h(mmap_start), host_len, prot, flags | MAP_FIXED | MAP_ANONYMOUS, -1, 0); if (p == MAP_FAILED) goto fail; /* update start so that it points to the file position at 'offset' */ host_start = (unsigned long)p; if (!(flags & MAP_ANONYMOUS)) { p = mmap(g2h(mmap_start), len, prot, flags | MAP_FIXED, fd, host_offset); host_start += offset - host_offset; } start = h2g(host_start); } else { if (start & ~TARGET_PAGE_MASK) { errno = EINVAL; goto fail; } end = start + len; real_end = HOST_PAGE_ALIGN(end); /* * Test if requested memory area fits target address space * It can fail only on 64-bit host with 32-bit target. * On any other target/host host mmap() handles this error correctly. */ if ((unsigned long)start + len - 1 > (abi_ulong) -1) { errno = EINVAL; goto fail; } /* worst case: we cannot map the file because the offset is not aligned, so we read it */ if (!(flags & MAP_ANONYMOUS) && (offset & ~qemu_host_page_mask) != (start & ~qemu_host_page_mask)) { /* msync() won't work here, so we return an error if write is possible while it is a shared mapping */ if ((flags & MAP_TYPE) == MAP_SHARED && (prot & PROT_WRITE)) { errno = EINVAL; goto fail; } retaddr = target_mmap(start, len, prot | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (retaddr == -1) goto fail; if (pread(fd, g2h(start), len, offset) == -1) goto fail; if (!(prot & PROT_WRITE)) { ret = target_mprotect(start, len, prot); if (ret != 0) { start = ret; goto the_end; } } goto the_end; } /* handle the start of the mapping */ if (start > real_start) { if (real_end == real_start + qemu_host_page_size) { /* one single host page */ ret = mmap_frag(real_start, start, end, prot, flags, fd, offset); if (ret == -1) goto fail; goto the_end1; } ret = mmap_frag(real_start, start, real_start + qemu_host_page_size, prot, flags, fd, offset); if (ret == -1) goto fail; real_start += qemu_host_page_size; } /* handle the end of the mapping */ if (end < real_end) { ret = mmap_frag(real_end - qemu_host_page_size, real_end - qemu_host_page_size, real_end, prot, flags, fd, offset + real_end - qemu_host_page_size - start); if (ret == -1) goto fail; real_end -= qemu_host_page_size; } /* map the middle (easier) */ if (real_start < real_end) { void *p; unsigned long offset1; if (flags & MAP_ANONYMOUS) offset1 = 0; else offset1 = offset + real_start - start; p = mmap(g2h(real_start), real_end - real_start, prot, flags, fd, offset1); if (p == MAP_FAILED) goto fail; } } the_end1: page_set_flags(start, start + len, prot | PAGE_VALID); the_end: #ifdef DEBUG_MMAP printf("ret=0x" TARGET_ABI_FMT_lx "\n", start); page_dump(stdout); printf("\n"); #endif if ((prot & PROT_EXEC) && (qemu_log_enabled() || tcg_plugin_enabled())) { load_symbols(fd, start); } mmap_unlock(); return start; fail: mmap_unlock(); return -1; }
int main(int argc, char **argv) { /* * The + on the front tells GNU getopt not to rearrange argv. */ const char *optlist = "+F:f:v:W;m:bcCd::D::e:E:gh:i:l:L:nNo::Op::MPrStVY"; bool stopped_early = false; int old_optind; int i; int c; char *scan, *src; char *extra_stack; int have_srcfile = 0; SRCFILE *s; /* do these checks early */ if (getenv("TIDYMEM") != NULL) do_flags |= DO_TIDY_MEM; #ifdef HAVE_MCHECK_H #ifdef HAVE_MTRACE if (do_tidy_mem) mtrace(); #endif /* HAVE_MTRACE */ #endif /* HAVE_MCHECK_H */ #if defined(LC_CTYPE) setlocale(LC_CTYPE, ""); #endif #if defined(LC_COLLATE) setlocale(LC_COLLATE, ""); #endif #if defined(LC_MESSAGES) setlocale(LC_MESSAGES, ""); #endif #if defined(LC_NUMERIC) && defined(HAVE_LOCALE_H) /* * Force the issue here. According to POSIX 2001, decimal * point is used for parsing source code and for command-line * assignments and the locale value for processing input, * number to string conversion, and printing output. * * 10/2005 --- see below also; we now only use the locale's * decimal point if do_posix in effect. * * 9/2007: * This is a mess. We need to get the locale's numeric info for * the thousands separator for the %'d flag. */ setlocale(LC_NUMERIC, ""); init_locale(& loc); setlocale(LC_NUMERIC, "C"); #endif #if defined(LC_TIME) setlocale(LC_TIME, ""); #endif #if MBS_SUPPORT /* * In glibc, MB_CUR_MAX is actually a function. This value is * tested *a lot* in many speed-critical places in gawk. Caching * this value once makes a speed difference. */ gawk_mb_cur_max = MB_CUR_MAX; /* Without MBS_SUPPORT, gawk_mb_cur_max is 1. */ /* init the cache for checking bytes if they're characters */ init_btowc_cache(); #endif (void) bindtextdomain(PACKAGE, LOCALEDIR); (void) textdomain(PACKAGE); (void) signal(SIGFPE, catchsig); #ifdef SIGBUS (void) signal(SIGBUS, catchsig); #endif (void) sigsegv_install_handler(catchsegv); #define STACK_SIZE (16*1024) emalloc(extra_stack, char *, STACK_SIZE, "main"); (void) stackoverflow_install_handler(catchstackoverflow, extra_stack, STACK_SIZE); #undef STACK_SIZE myname = gawk_name(argv[0]); os_arg_fixup(&argc, &argv); /* emulate redirection, expand wildcards */ if (argc < 2) usage(EXIT_FAILURE, stderr); /* initialize the null string */ Nnull_string = make_string("", 0); /* Robustness: check that file descriptors 0, 1, 2 are open */ init_fds(); /* init array handling. */ array_init(); /* init the symbol tables */ init_symbol_table(); output_fp = stdout; /* we do error messages ourselves on invalid options */ opterr = false; /* copy argv before getopt gets to it; used to restart the debugger */ save_argv(argc, argv); /* initialize global (main) execution context */ push_context(new_context()); /* option processing. ready, set, go! */ for (optopt = 0, old_optind = 1; (c = getopt_long(argc, argv, optlist, optab, NULL)) != EOF; optopt = 0, old_optind = optind) { if (do_posix) opterr = true; switch (c) { case 'F': add_preassign(PRE_ASSIGN_FS, optarg); break; case 'E': disallow_var_assigns = true; /* fall through */ case 'f': /* * Allow multiple -f options. * This makes function libraries real easy. * Most of the magic is in the scanner. * * The following is to allow for whitespace at the end * of a #! /bin/gawk line in an executable file */ scan = optarg; if (argv[optind-1] != optarg) while (isspace((unsigned char) *scan)) scan++; src = (*scan == '\0' ? argv[optind++] : optarg); (void) add_srcfile((src && src[0] == '-' && src[1] == '\0') ? SRC_STDIN : SRC_FILE, src, srcfiles, NULL, NULL); break; case 'v': add_preassign(PRE_ASSIGN, optarg); break; case 'm': /* * BWK awk extension. * -mf nnn set # fields, gawk ignores * -mr nnn set record length, ditto * * As of at least 10/2007, BWK awk also ignores it. */ if (do_lint) lintwarn(_("`-m[fr]' option irrelevant in gawk")); if (optarg[0] != 'r' && optarg[0] != 'f') warning(_("-m option usage: `-m[fr] nnn'")); break; case 'b': do_binary = true; break; case 'c': do_flags |= DO_TRADITIONAL; break; case 'C': copyleft(); break; case 'd': do_flags |= DO_DUMP_VARS; if (optarg != NULL && optarg[0] != '\0') varfile = optarg; break; case 'D': do_flags |= DO_DEBUG; if (optarg != NULL && optarg[0] != '\0') command_file = optarg; break; case 'e': if (optarg[0] == '\0') warning(_("empty argument to `-e/--source' ignored")); else (void) add_srcfile(SRC_CMDLINE, optarg, srcfiles, NULL, NULL); break; case 'g': do_flags |= DO_INTL; break; case 'h': /* write usage to stdout, per GNU coding stds */ usage(EXIT_SUCCESS, stdout); break; case 'i': (void) add_srcfile(SRC_INC, optarg, srcfiles, NULL, NULL); break; case 'l': (void) add_srcfile(SRC_EXTLIB, optarg, srcfiles, NULL, NULL); break; case 'L': #ifndef NO_LINT do_flags |= DO_LINT_ALL; if (optarg != NULL) { if (strcmp(optarg, "fatal") == 0) lintfunc = r_fatal; else if (strcmp(optarg, "invalid") == 0) { do_flags &= ~DO_LINT_ALL; do_flags |= DO_LINT_INVALID; } } break; case 't': do_flags |= DO_LINT_OLD; break; #else case 'L': case 't': break; #endif case 'n': do_flags |= DO_NON_DEC_DATA; break; case 'N': use_lc_numeric = true; break; case 'O': do_optimize++; break; case 'p': do_flags |= DO_PROFILE; /* fall through */ case 'o': do_flags |= DO_PRETTY_PRINT; if (optarg != NULL) set_prof_file(optarg); else set_prof_file(DEFAULT_PROFILE); break; case 'M': #ifdef HAVE_MPFR do_flags |= DO_MPFR; #endif break; case 'P': do_flags |= DO_POSIX; break; case 'r': do_flags |= DO_INTERVALS; break; case 'S': do_flags |= DO_SANDBOX; break; case 'V': do_version = true; break; case 'W': /* gawk specific options - now in getopt_long */ fprintf(stderr, _("%s: option `-W %s' unrecognized, ignored\n"), argv[0], optarg); break; case 0: /* * getopt_long found an option that sets a variable * instead of returning a letter. Do nothing, just * cycle around for the next one. */ break; case 'Y': #if defined(YYDEBUG) || defined(GAWKDEBUG) if (c == 'Y') { yydebug = 2; break; } #endif /* if not debugging, fall through */ case '?': default: /* * If not posix, an unrecognized option stops argument * processing so that it can go into ARGV for the awk * program to see. This makes use of ``#! /bin/gawk -f'' * easier. * * However, it's never simple. If optopt is set, * an option that requires an argument didn't get the * argument. We care because if opterr is 0, then * getopt_long won't print the error message for us. */ if (! do_posix && (optopt == '\0' || strchr(optlist, optopt) == NULL)) { /* * can't just do optind--. In case of an * option with >= 2 letters, getopt_long * won't have incremented optind. */ optind = old_optind; stopped_early = true; goto out; } else if (optopt != '\0') { /* Use POSIX required message format */ fprintf(stderr, _("%s: option requires an argument -- %c\n"), myname, optopt); usage(EXIT_FAILURE, stderr); } /* else let getopt print error message for us */ break; } if (c == 'E') /* --exec ends option processing */ break; } out: if (do_nostalgia) nostalgia(); /* check for POSIXLY_CORRECT environment variable */ if (! do_posix && getenv("POSIXLY_CORRECT") != NULL) { do_flags |= DO_POSIX; if (do_lint) lintwarn( _("environment variable `POSIXLY_CORRECT' set: turning on `--posix'")); } if (do_posix) { use_lc_numeric = true; if (do_traditional) /* both on command line */ warning(_("`--posix' overrides `--traditional'")); else do_flags |= DO_TRADITIONAL; /* * POSIX compliance also implies * no GNU extensions either. */ } if (do_traditional && do_non_decimal_data) { do_flags &= ~DO_NON_DEC_DATA; warning(_("`--posix'/`--traditional' overrides `--non-decimal-data'")); } if (do_lint && os_is_setuid()) warning(_("running %s setuid root may be a security problem"), myname); #if MBS_SUPPORT if (do_binary) { if (do_posix) warning(_("`--posix' overrides `--characters-as-bytes'")); else gawk_mb_cur_max = 1; /* hands off my data! */ #if defined(LC_ALL) setlocale(LC_ALL, "C"); #endif } #endif if (do_debug) /* Need to register the debugger pre-exec hook before any other */ init_debug(); #ifdef HAVE_MPFR /* Set up MPFR defaults, and register pre-exec hook to process arithmetic opcodes */ if (do_mpfr) init_mpfr(DEFAULT_PREC, DEFAULT_ROUNDMODE); #endif /* load group set */ init_groupset(); #ifdef HAVE_MPFR if (do_mpfr) { mpz_init(Nnull_string->mpg_i); Nnull_string->flags = (MALLOC|STRCUR|STRING|MPZN|NUMCUR|NUMBER); } else #endif { Nnull_string->numbr = 0.0; Nnull_string->flags = (MALLOC|STRCUR|STRING|NUMCUR|NUMBER); } /* * Tell the regex routines how they should work. * Do this before initializing variables, since * they could want to do a regexp compile. */ resetup(); /* Set up the special variables */ init_vars(); /* Set up the field variables */ init_fields(); /* Now process the pre-assignments */ for (i = 0; i <= numassigns; i++) { if (preassigns[i].type == PRE_ASSIGN) (void) arg_assign(preassigns[i].val, true); else /* PRE_ASSIGN_FS */ cmdline_fs(preassigns[i].val); efree(preassigns[i].val); } if (preassigns != NULL) efree(preassigns); if ((BINMODE & 1) != 0) if (os_setbinmode(fileno(stdin), O_BINARY) == -1) fatal(_("can't set binary mode on stdin (%s)"), strerror(errno)); if ((BINMODE & 2) != 0) { if (os_setbinmode(fileno(stdout), O_BINARY) == -1) fatal(_("can't set binary mode on stdout (%s)"), strerror(errno)); if (os_setbinmode(fileno(stderr), O_BINARY) == -1) fatal(_("can't set binary mode on stderr (%s)"), strerror(errno)); } #ifdef GAWKDEBUG setbuf(stdout, (char *) NULL); /* make debugging easier */ #endif if (os_isatty(fileno(stdout))) output_is_tty = true; /* initialize API before loading extension libraries */ init_ext_api(); /* load extension libs */ for (s = srcfiles->next; s != srcfiles; s = s->next) { if (s->stype == SRC_EXTLIB) load_ext(s->fullpath); else if (s->stype != SRC_INC) have_srcfile++; } /* do version check after extensions are loaded to get extension info */ if (do_version) version(); /* No -f or --source options, use next arg */ if (! have_srcfile) { if (optind > argc - 1 || stopped_early) /* no args left or no program */ usage(EXIT_FAILURE, stderr); (void) add_srcfile(SRC_CMDLINE, argv[optind], srcfiles, NULL, NULL); optind++; } /* Select the interpreter routine */ init_interpret(); init_args(optind, argc, do_posix ? argv[0] : myname, argv); #if defined(LC_NUMERIC) /* * FRAGILE! CAREFUL! * Pre-initing the variables with arg_assign() can change the * locale. Force it to C before parsing the program. */ setlocale(LC_NUMERIC, "C"); #endif /* Read in the program */ if (parse_program(& code_block) != 0) exit(EXIT_FAILURE); if (do_intl) exit(EXIT_SUCCESS); if (do_lint) shadow_funcs(); if (do_lint && code_block->nexti->opcode == Op_atexit) lintwarn(_("no program text at all!")); load_symbols(); if (do_profile) init_profiling_signals(); #if defined(LC_NUMERIC) /* * See comment above about using locale's decimal point. * * 10/2005: * Bitter experience teaches us that most people the world over * use period as the decimal point, not whatever their locale * uses. Thus, only use the locale's decimal point if being * posixly anal-retentive. * * 7/2007: * Be a little bit kinder. Allow the --use-lc-numeric option * to also use the local decimal point. This avoids the draconian * strictness of POSIX mode if someone just wants to parse their * data using the local decimal point. */ if (use_lc_numeric) setlocale(LC_NUMERIC, ""); #endif init_io(); output_fp = stdout; if (do_debug) debug_prog(code_block); else interpret(code_block); if (do_pretty_print) { dump_prog(code_block); dump_funcs(); } if (do_dump_vars) dump_vars(varfile); if (do_tidy_mem) release_all_vars(); /* keep valgrind happier */ if (extra_stack) efree(extra_stack); final_exit(exit_val); return exit_val; /* to suppress warnings */ }
static int idaapi notify(processor_t::idp_notify msgid, ...) { va_list va; va_start(va, msgid); // A well behaving processor module should call invoke_callbacks() // in his notify() function. If this function returns 0, then // the processor module should process the notification itself // Otherwise the code should be returned to the caller: int code = invoke_callbacks(HT_IDP, msgid, va); if ( code ) return code; switch ( msgid ) { case processor_t::init: // __emit__(0xCC); // debugger trap helper.create("$ h8"); helper.supval(0, device, sizeof(device)); inf.mf = 1; default: break; /* +++ START TYPEINFO CALLBACKS +++ */ // see module/{i960,hppa}/reg.cpp starting on line 253 // Decorate/undecorate a C symbol name // Arguments: // const til_t *ti - pointer to til // const char *name - name of symbol // const type_t *type - type of symbol. If NULL then it will try to guess. // char *outbuf - output buffer // size_t bufsize - size of the output buffer // bool mangle - true-mangle, false-unmangle // cm_t cc - real calling convention for VOIDARG functions // returns: true if success case processor_t::decorate_name: { const til_t *ti = va_arg(va, const til_t *); const char *name = va_arg(va, const char *); const type_t *type = va_arg(va, const type_t *); char *outbuf = va_arg(va, char *); size_t bufsize = va_arg(va, size_t); bool mangle = va_argi(va, bool); cm_t real_cc = va_argi(va, cm_t); return gen_decorate_name(ti, name, type, outbuf, bufsize, mangle, real_cc); } // Setup default type libraries (called after loading a new file into the database) // The processor module may load tils, setup memory model and perform other actions // required to set up the type system. // args: none // returns: nothing case processor_t::setup_til: { } // Purpose: get prefix and size of 'segment based' ptr type (something like // char _ss *ptr). See description in typeinf.hpp. // Other modules simply set the pointer to NULL and return 0 // Ilfak confirmed that this approach is correct for the H8. // Used only for BTMT_CLOSURE types, doubtful you will encounter them for H8. // Arguments: // unsigned int ptrt - ... // const char **ptrname - output arg // returns: size of type case processor_t::based_ptr: { /*unsigned int ptrt =*/ va_arg(va, unsigned int); char **ptrname = va_arg(va, char **); *ptrname = NULL; return 0; } // The H8 supports normal (64KB addressing, 16 bits) and advanced mode // (16MB addressing, 24 bits). However, according to the Renesas technical // documentation, certain instructions accept 32-bit pointer values where // the upper 8 bits are "reserved". Ilfak confirms that "4+1" is fine. // Used only for BTMT_CLOSURE types, doubtful you will encounter them for H8. case processor_t::max_ptr_size: { return 4+1; } // get default enum size // args: cm_t cm // returns: sizeof(enum) case processor_t::get_default_enum_size: { // cm_t cm = va_argi(va, cm_t); return inf.cc.size_e; } case processor_t::use_stkarg_type: { ea_t ea = va_arg(va, ea_t); const type_t *type = va_arg(va, const type_t *); const char *name = va_arg(va, const char *); return h8_use_stkvar_type(ea, type, name); } // calculate number of purged bytes by the given function type // For cdecl functions, 'purged bytes' is always zero // See the IDA Pro Book, 2e, at the end of pp. 107 for details // args: type_t *type - must be function type // returns: number of bytes purged from the stack + 2 case processor_t::calc_purged_bytes: { //e.g. const type_t t_int[] = { BT_INT, 0 }; //const type_t *type = va_arg(va, const type_t *); // must be BT_FUNC return 0+2; } case processor_t::calc_arglocs2: { const type_t *type = va_arg(va, const type_t *); cm_t cc = va_argi(va, cm_t); varloc_t *arglocs = va_arg(va, varloc_t *); return h8_calc_arglocs(type, cc, arglocs); } /* +++ END TYPEINFO CALLBACKS +++ */ case processor_t::term: free_ioports(ports, numports); break; case processor_t::newfile: // new file loaded load_symbols(); break; case processor_t::oldfile: // old file loaded load_symbols(); break; case processor_t::closebase: case processor_t::savebase: helper.supset(0, device); break; case processor_t::newprc: // new processor type ptype = ptypes[va_arg(va, int)]; setflag(ph.flag, PR_DEFSEG32, ptype & ADV); break; case processor_t::newasm: // new assembler type break; case processor_t::newseg: // new segment break; case processor_t::is_jump_func: { const func_t *pfn = va_arg(va, const func_t *); ea_t *jump_target = va_arg(va, ea_t *); return is_jump_func(pfn, jump_target); } case processor_t::is_sane_insn: return is_sane_insn(va_arg(va, int)); case processor_t::may_be_func: // can a function start here? // arg: none, the instruction is in 'cmd' // returns: probability 0..100 // 'cmd' structure is filled upon the entrace // the idp module is allowed to modify 'cmd' return may_be_func(); } va_end(va); return 1; }
int main(int argc, char *argv[]) { kvm_t *kd; pid_t pid; uid_t uid; int which, many, ch, rc; char errbuf[_POSIX2_LINE_MAX + 1]; struct kinfo_proc2 *kproc; char *kmem, *kernel, *t; gid_t egid; struct kbit kbit, *vmspace; u_long address; egid = getegid(); if (setegid(getgid()) == -1) err(1, "failed to reset privileges"); check_fd(STDIN_FILENO); check_fd(STDOUT_FILENO); check_fd(STDERR_FILENO); pid = -1; which = verbose = debug = 0; print_all = print_map = print_maps = print_solaris = print_ddb = 0; recurse = 0; kmem = kernel = NULL; address = 0; vmspace = &kbit; while ((ch = getopt(argc, argv, "A:aD:dE:lM:mN:Pp:RrS:sV:vx")) != -1) { switch (ch) { case 'A': case 'E': case 'S': case 'V': if (which != 0) errx(1, "use only one of -A, -E, -S, or -V"); errno = 0; address = strtoul(optarg, &t, 0); if (*t != '\0') errx(1, "%s is not a valid address", optarg); if (errno != 0) err(1, "%s is not a valid address", optarg); switch (ch) { case 'A': which = AMAP_ADDRESS; break; case 'E': which = VM_MAP_ENTRY_ADDRESS; break; case 'S': which = VMSPACE_ADDRESS; break; case 'V': which = VM_MAP_ADDRESS; break; } break; case 'a': print_all = 1; break; case 'd': print_ddb = 1; break; case 'D': errno = 0; debug = strtoul(optarg, &t, 0); if (*t != '\0') errx(1, "%s is not a valid number", optarg); if (errno != 0) err(1, "%s is not a valid number", optarg); break; case 'l': print_maps = 1; break; case 'm': print_map = 1; break; case 'M': kmem = optarg; break; case 'N': kernel = optarg; break; case 'p': errno = 0; pid = strtol(optarg, &t, 0); if (pid < 0) errno = EINVAL; if (*t != '\0') errx(1, "%s is not a valid pid", optarg); if (errno != 0) err(1, "%s is not a valid pid", optarg); break; case 'P': pid = getpid(); break; case 'R': recurse = 1; break; case 's': print_solaris = 1; break; case 'v': verbose++; break; case 'r': case 'x': errx(1, "-%c option not implemented, sorry", optopt); /*NOTREACHED*/ case '?': default: fprintf(stderr, "usage: %s [-adlmPRsv] [-A address] " "[-D number] [-E address] [-M core]\n" "\t[-N system] [-p pid] [-S address] " "[-V address] [pid ...]\n", getprogname()); exit(1); } } argc -= optind; argv += optind; /* more than one "process" to dump? */ many = (argc > 1 - (pid == -1 ? 0 : 1)) ? 1 : 0; /* apply default */ if (print_all + print_map + print_maps + print_solaris + print_ddb == 0) print_solaris = 1; /* get privs back if it appears to be safe, otherwise toss them */ if (kernel == NULL && kmem == NULL && address == 0) rc = setegid(egid); else rc = setgid(getgid()); if (rc == -1) err(1, "failed to reset privileges"); /* start by opening libkvm */ kd = kvm_openfiles(kernel, kmem, NULL, O_RDONLY, errbuf); /* we're completely done with privileges now */ rc = setgid(getgid()); if (rc == -1) err(1, "failed to reset privileges"); /* print the kvm_open error, if any */ errbuf[_POSIX2_LINE_MAX] = '\0'; if (kd == NULL) errx(1, "%s", errbuf); /* get "bootstrap" addresses from kernel */ load_symbols(kd); if (address) { struct kbit kbit2, *at = &kbit2; memset(vmspace, 0, sizeof(*vmspace)); A(at) = address; S(at) = (size_t)-1; switch (which) { case VMSPACE_ADDRESS: /* (kd, kproc, vmspace, thing) */ (*process_map)(kd, NULL, at, "vm_map"); break; case VM_MAP_ADDRESS: /* (kd, proc, vmspace, vm_map, thing) */ (*dump_vm_map)(kd, NULL, vmspace, at, "vm_map"); break; case VM_MAP_ENTRY_ADDRESS: /* (kd, proc, vmspace, vm_map_entry, 0) */ (*dump_vm_map_entry)(kd, NULL, vmspace, at, 0); break; case AMAP_ADDRESS: /* (kd, amap) */ (*dump_amap)(kd, at); break; } exit(0); } uid = getuid(); do { if (pid == -1) { if (argc == 0) pid = getppid(); else { errno = 0; pid = strtol(argv[0], &t, 0); if (pid < 0) errno = EINVAL; if (*t != '\0') errx(1, "%s is not a valid pid", argv[0]); if (errno != 0) err(1, "%s is not a valid pid", argv[0]); argv++; argc--; } } errno = 0; /* find the process id */ if (pid == 0) { kproc = NULL; if (uid != 0) { /* only root can print kernel mappings */ errno = EPERM; } } else { kproc = kvm_getproc2(kd, KERN_PROC_PID, pid, sizeof(struct kinfo_proc2), &rc); if (kproc == NULL || rc == 0) { errno = ESRCH; } else if (uid != 0 && uid != kproc->p_uid) { /* * only the real owner of the process and * root can print process mappings */ errno = EPERM; } } if (errno != 0) { warn("%d", pid); pid = -1; continue; } /* dump it */ if (many) { if (kproc != NULL) printf("process %d:\n", kproc->p_pid); else printf("kernel:\n"); } (*process_map)(kd, kproc, vmspace, NULL); pid = -1; } while (argc > 0); /* done. go away. */ rc = kvm_close(kd); if (rc == -1) err(1, "kvm_close"); return (0); }