@global core_defined; if (core_defined == nil) { @local align,parse_core; @global mkcoreas; core_defined = 1; @include @define align(l, sz) { @local res; res = l; if (l % sz) res = l + (sz - (l % sz)); return res; } // returns [regptr, address_ranges] @define parse_core(elfdom, fname) { @local ehdr; @local pharray, p, i, is32; @local addr_ranges, start_paddr, start_vaddr, reg_size; @local regptr; if (sizeof (nsptr (elfdom.ns)) == 4) { ehdr = (elfdom`Elf32_Ehdr *){elfdom} 0; pharray = (elfdom`Elf32_Phdr *) ehdr->e_phoff; is32 = 1; } else { ehdr = (elfdom`Elf64_Ehdr *){elfdom} 0; pharray = (elfdom`Elf64_Phdr *) ehdr->e_phoff; is32 = 0; } if (ehdr->e_type != elfdom`ET_CORE) { error("Are you sure %s is a corefile?", fname); } // format: [[lower1, upper1, fptr], [lower2, upper2, fptr], ...] addr_ranges = []; regptr = nil; start_paddr = 0; start_vaddr = 0; reg_size = 0; for (i = 0; i < ehdr->e_phnum; i++) { p = pharray + i; if (p->p_type == elfdom`PT_NOTE) { @local cur; cur = p->p_offset; while (cur < p->p_offset + p->p_filesz) { @local nhdr; if (is32) { nhdr = (elfdom`Elf32_Nhdr *) cur; } else { nhdr = (elfdom`Elf64_Nhdr *) cur; } // cur is now data beginning cur = cur + sizeof(*nhdr) + align(nhdr->n_namesz, 4); if (nhdr->n_type == elfdom`NT_PRSTATUS && nhdr->n_descsz == sizeof(struct elfdom`elf_prstatus_32)) { @local prstatus; prstatus = (struct elfdom`elf_prstatus_32 *)cur; regptr = prstatus->pr_reg; break; } cur = cur + align(nhdr->n_descsz, 4); } } else if (p->p_type == elfdom`PT_LOAD && p->p_filesz) { // contiguous region, just add on to what's there if (start_paddr + reg_size == p->p_offset && start_vaddr + reg_size == p->p_vaddr) { reg_size = reg_size + p->p_filesz; } // break in regions, not the first one else { if(start_paddr != 0) append(addr_ranges, [start_vaddr, start_vaddr + reg_size - 1, (unsigned char *){elfdom}start_paddr]); start_paddr = p->p_offset; start_vaddr = p->p_vaddr; reg_size = p->p_filesz; } } } if(start_paddr != 0) { append(addr_ranges, [start_vaddr, start_vaddr + reg_size - 1, (unsigned char *){elfdom}start_paddr]); } return [regptr, addr_ranges]; } /** * param: fname - name of the core file * returns: address space for the provided core file. */ @define mkcoreas(fname) { @local elfdom; @local addr_ranges, regptr, parseout; @local mapped_ranges,dispatch; elfdom = mkelfrec(mapfile(fname)).elf; parseout = parse_core(elfdom, fname); addr_ranges = listref(parseout, 1); regptr = listref(parseout, 0); //for (i = 0; i < length(addr_ranges); i++) { //@local l; //l = listref(addr_ranges, i); // printf("%x: %x - %x\n", listref(l, 2), listref(l, 0), listref(l, 1)); //} //precompute ranges for .map(). mapped_ranges = map(@lambda(x) { return mkrange(x[0],x[1]-x[0]-1); },addr_ranges); mapped_ranges = apply(vector,mapped_ranges); @define dispatch (args ...) { @local arg, r, beg, len, i; arg = listref(args, 1); if (arg == "get") { r = listref(args, 2); beg = rangebeg(r); len = rangelen(r); //check for overflow if (beg + len < beg) fault(); for (i = 0; i < length(addr_ranges); i++) { @local l, vbeg, vend; l = listref(addr_ranges, i); vbeg = listref(l, 0); vend = listref(l, 1); if (vbeg <= beg && vend > beg + len) { return getbytes(listref(l,2) + (beg - vbeg), len); } } fault(); } else if (arg == "map") { return mapped_ranges; } else if (arg == "ismapped") { return isrinr(args[2], mapped_ranges); } else if (arg == "put") { error("put() unimplemented for core address spaces."); } else if (arg == "getebx") { return regptr[0]; } else if (arg == "getecx") { return regptr[1]; } else if (arg == "getedx") { return regptr[2]; } else if (arg == "getesi") { return regptr[3]; } else if (arg == "getedi") { return regptr[4]; } else if (arg == "getebp") { return regptr[5]; } else if (arg == "geteax") { return regptr[6]; } else if (arg == "geteip") { return regptr[12]; } else if (arg == "geteflags") { return regptr[14]; } else if (arg == "getesp") { return regptr[15]; } error("bad argument to dispatch in core file %s\n", fname); } return mkas([ "dispatch" : dispatch ], fname); } }