static void doublefault_fn(void) { struct desc_ptr gdt_desc = {0, 0}; unsigned long gdt, tss; native_store_gdt(&gdt_desc); gdt = (unsigned long)gdt_desc.address; printk(KERN_EMERG "PANIC: double fault, gdt at %08lx [%d bytes]\n", gdt, gdt_desc.size); if (ptr_ok(gdt)) { gdt += GDT_ENTRY_TSS << 3; tss = get_desc_base((struct desc_struct *)gdt); printk(KERN_EMERG "double fault, tss at %08lx\n", tss); if (ptr_ok(tss)) { struct x86_hw_tss *t = (struct x86_hw_tss *)tss; printk(KERN_EMERG "eip = %08lx, esp = %08lx\n", t->ip, t->sp); printk(KERN_EMERG "eax = %08lx, ebx = %08lx, ecx = %08lx, edx = %08lx\n", t->ax, t->bx, t->cx, t->dx); printk(KERN_EMERG "esi = %08lx, edi = %08lx\n", t->si, t->di); } } for (;;) cpu_relax(); }
result() : ptr_ok_(ptr_ok()), ptr_error_(ptr_error()) {}
result(const result<Ok, Error>& other) : ptr_ok_(other.is_ok() ? ptr_ok(new Ok(other.unsafe_get_ok())) : ptr_ok()), ptr_error_(other.is_error() ? ptr_error(new Error(other.unsafe_get_error())) : ptr_error()) { check_either_or_invariant(); }
result<Ok, Error>& operator = (const result<Ok, Error>& other) { ptr_ok_ = other.is_ok() ? ptr_ok(new Ok(other.unsafe_get_ok())) : ptr_ok(); ptr_error_ = other.is_error() ? ptr_error(new Error(other.unsafe_get_error())) : ptr_error(); return *this; }
static void parse_elf(const char *exe) { int f; f = open(exe, O_RDONLY); if (f < 0) { if (!arg_quiet) fprintf(stderr, "Warning fldd: cannot open %s, skipping...\n", exe); return; } struct stat s; char *base = NULL, *end; if (fstat(f, &s) == -1) goto error_close; base = mmap(0, s.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, f, 0); if (base == MAP_FAILED) goto error_close; end = base + s.st_size; Elf_Ehdr *ebuf = (Elf_Ehdr *)base; if (strncmp((const char *)ebuf->e_ident, ELFMAG, SELFMAG) != 0) { if (!arg_quiet) fprintf(stderr, "Warning fldd: %s is not an ELF executable or library\n", exe); goto close; } //unsigned char elfclass = ebuf->e_ident[EI_CLASS]; //if (elfclass == ELFCLASS32) //printf("%s 32bit\n", exe); //else if (elfclass == ELFCLASS64) //printf("%s 64bit\n", exe); Elf_Phdr *pbuf = (Elf_Phdr *)(base + sizeof(*ebuf)); while (ebuf->e_phnum-- > 0 && ptr_ok(pbuf, base, end, "pbuf")) { switch (pbuf->p_type) { case PT_INTERP: // dynamic loader ld-linux.so if (!ptr_ok(base + pbuf->p_offset, base, end, "base + pbuf->p_offset")) goto close; storage_add(&libs, base + pbuf->p_offset); break; } pbuf++; } Elf_Shdr *sbuf = (Elf_Shdr *)(base + ebuf->e_shoff); if (!ptr_ok(sbuf, base, end, "sbuf")) goto close; // Find strings section char *strbase = NULL; int sections = ebuf->e_shnum; while (sections-- > 0 && ptr_ok(sbuf, base, end, "sbuf")) { if (sbuf->sh_type == SHT_STRTAB) { strbase = base + sbuf->sh_offset; if (!ptr_ok(strbase, base, end, "strbase")) goto close; break; } sbuf++; } if (strbase == NULL) goto error_close; // Find dynamic section sections = ebuf->e_shnum; while (sections-- > 0 && ptr_ok(sbuf, base, end, "sbuf")) { // TODO: running fldd on large gui programs (fldd /usr/bin/transmission-qt) // crash on accessing memory location sbuf->sh_type if sbuf->sh_type in the previous section was 0 (SHT_NULL) // for now we just exit the while loop - this is probably incorrect // printf("sbuf %p #%s#, sections %d, type %u\n", sbuf, exe, sections, sbuf->sh_type); if (!ptr_ok(sbuf, base, end, "sbuf")) goto close; if (sbuf->sh_type == SHT_NULL) break; if (sbuf->sh_type == SHT_DYNAMIC) { Elf_Dyn *dbuf = (Elf_Dyn *)(base + sbuf->sh_offset); if (!ptr_ok(dbuf, base, end, "dbuf")) goto close; // Find DT_RPATH/DT_RUNPATH tags first unsigned long size = sbuf->sh_size; while (size >= sizeof(*dbuf) && ptr_ok(dbuf, base, end, "dbuf")) { if (dbuf->d_tag == DT_RPATH || dbuf->d_tag == DT_RUNPATH) { const char *searchpath = strbase + dbuf->d_un.d_ptr; if (!ptr_ok(searchpath, base, end, "searchpath")) goto close; storage_add(&lib_paths, searchpath); } size -= sizeof(*dbuf); dbuf++; } // Find DT_NEEDED tags dbuf = (Elf_Dyn *)(base + sbuf->sh_offset); size = sbuf->sh_size; while (size >= sizeof(*dbuf) && ptr_ok(dbuf, base, end, "dbuf")) { if (dbuf->d_tag == DT_NEEDED) { const char *lib = strbase + dbuf->d_un.d_ptr; if (!ptr_ok(lib, base, end, "lib")) goto close; copy_libs_for_lib(lib); } size -= sizeof(*dbuf); dbuf++; } } sbuf++; } goto close; error_close: perror("copy libs"); close: if (base) munmap(base, s.st_size); close(f); }