예제 #1
0
void load_dll_crt(uint32_t pid, const wchar_t *dll_path)
{
    load_library_t s;
    memset(&s, 0, sizeof(s));

    s.ldr_load_dll = resolve_symbol("ntdll", "LdrLoadDll");
    s.get_last_error = resolve_symbol("ntdll", "RtlGetLastWin32Error");

    s.filepath.Length = lstrlenW(dll_path) * sizeof(wchar_t);
    s.filepath.MaximumLength = strsizeW(dll_path);
    s.filepath.Buffer = write_data(pid, dll_path, strsizeW(dll_path));

    void *settings_addr = write_data(pid, &s, sizeof(s));
    void *shellcode_addr = write_data(pid, &load_library_worker, 0x1000);

    // Run LdrLoadDll(..., dll_path, ...) in the target process.
    uint32_t last_error =
        create_thread_and_wait(pid, shellcode_addr, settings_addr);
    if(last_error != 0) {
        error("[-] Error loading monitor into process: %d\n", last_error);
    }

    free_data(pid, s.filepath.Buffer, strsizeW(dll_path));
    free_data(pid, settings_addr, sizeof(s));
    free_data(pid, shellcode_addr, 0x1000);
}
예제 #2
0
void load_dll_apc(uint32_t pid, uint32_t tid, const wchar_t *dll_path)
{
    load_library_t s;
    memset(&s, 0, sizeof(s));

    s.ldr_load_dll = resolve_symbol("ntdll", "LdrLoadDll");
    s.get_last_error = resolve_symbol("ntdll", "RtlGetLastWin32Error");

    s.filepath.Length = lstrlenW(dll_path) * sizeof(wchar_t);
    s.filepath.MaximumLength = strsizeW(dll_path);
    s.filepath.Buffer = write_data(pid, dll_path, strsizeW(dll_path));

    void *settings_addr = write_data(pid, &s, sizeof(s));
    void *shellcode_addr = write_data(pid, &load_library_worker, 0x1000);

    HANDLE thread_handle = open_thread(tid);

    // Add LdrLoadDll(..., dll_path, ...) to the APC queue.
    if(QueueUserAPC((PAPCFUNC) shellcode_addr, thread_handle,
            (ULONG_PTR) settings_addr) == 0) {
        error("[-] Error adding task to APC queue: %ld\n", GetLastError());
    }

    // TODO Come up with a way to deallocate dll_addr.
    CloseHandle(thread_handle);
}
예제 #3
0
static bool
backtrace_test ()
{
  free (resolve_symbol (puts));
  free (resolve_symbol (puts));
#if 0
  for (int i = 0; i < 10; i++)
    make_stack ();
#endif
  exit (0);
  return true;
}
예제 #4
0
u64 resolve_symbol_tab(inject_ctx *ctx, char *name) {
	u64 sym;

	if (ctx->dynsym != 0 && ctx->dynstr != 0) {
		sym = resolve_symbol(ctx->dynsym, ctx->dynsym_sz, (char*)ctx->dynstr, name);
	}

	if (sym == 0 && ctx->symtab != 0 && ctx->strtab != 0) {
		sym = resolve_symbol(ctx->symtab, ctx->symtab_sz, (char*)ctx->strtab, name);
	}

	if (sym != 0) {
		sym += ctx->elf_base;
	}

	return sym;
}
예제 #5
0
void
exit_plugin(void *handle)
{
	int (*exit)(void *);

	exit = resolve_symbol("cifs_idmap_exit_plugin");
	if (exit)
		(*exit)(handle);
}
예제 #6
0
 /// Adds a symbol and returns its ID. Can also be used to look-up a symbol.
 ID add_symbol(Symbol new_symbol) {
     ID result = resolve_symbol(new_symbol);
     if (result >= 0) { // the new symbol does already exist
         return result;
     } else {
         // add symbol to signature
         VLOG(9) << "Signature: New mapping added: '" << new_symbol << "' <-> " << number_of_entries();
         external_to_internal[new_symbol] = number_of_entries();
         internal_to_external.push_back(new_symbol);
         return number_of_entries() - 1;
     }
 }
예제 #7
0
파일: module.c 프로젝트: Jokymon/barebox
/* Change all symbols so that sh_value encodes the pointer directly. */
static int simplify_symbols(Elf32_Shdr *sechdrs,
			    unsigned int symindex,
			    const char *strtab)
{
	Elf32_Sym *sym = (void *)sechdrs[symindex].sh_addr;
	unsigned long secbase;
	unsigned int i, n = sechdrs[symindex].sh_size / sizeof(Elf32_Sym);
	int ret = 0;

	for (i = 1; i < n; i++) {
		switch (sym[i].st_shndx) {
		case SHN_COMMON:
			/* We compiled with -fno-common.  These are not
			   supposed to happen.  */
			printf("Common symbol: %s\n", strtab + sym[i].st_name);
			printf("please compile with -fno-common\n");
			ret = -1;
			break;

		case SHN_ABS:
			/* Don't need to do anything */
			debug("Absolute symbol: 0x%08lx\n",
			       (long)sym[i].st_value);
			break;

		case SHN_UNDEF:
			sym[i].st_value
			  = resolve_symbol(sechdrs,
					   strtab + sym[i].st_name);
			debug("undef  : %20s 0x%08x 0x%08lx\n", strtab + sym[i].st_name, sym[i].st_value);

			/* Ok if resolved.  */
			if (sym[i].st_value != 0)
				break;
			/* Ok if weak.  */
			if (ELF32_ST_BIND(sym[i].st_info) == STB_WEAK)
				break;

			printf("Unknown symbol %s\n",
			       strtab + sym[i].st_name);
			ret = -1;
			break;

		default:
			secbase = sechdrs[sym[i].st_shndx].sh_addr;
			debug("default: %20s 0x%08x 0x%08lx\n", strtab + sym[i].st_name, sym[i].st_value, secbase);
			sym[i].st_value += secbase;
			break;
		}
	}

	return ret;
}
예제 #8
0
파일: mod.c 프로젝트: chyyuu/ucore-driver
static int simplify_symbols(struct secthdr *sechdrs,
			    unsigned int symindex,
			    const char *strtab,
			    unsigned int versindex,
			    unsigned int pcpuindex, struct module *mod)
{
	struct symtab_s *sym = (void *)sechdrs[symindex].sh_addr;
	unsigned long secbase;
	unsigned int i, n = sechdrs[symindex].sh_size / sizeof(struct symtab_s);
	int ret = 0;
	const struct kernel_symbol *ksym;
	for (i = 1; i < n; i++) {
		switch (sym[i].st_shndx) {
		case SHN_COMMON:
			/* We compiled with -fno-common.  These are not supposed to happen.  */
			kprintf("simplify_symbols: Common symbol: %s\n",
				strtab + sym[i].st_name);
			kprintf("%s: please compile with -fno-common\n",
				mod->name);
			ret = -1;
			break;
		case SHN_ABS:
			/* Don't need to do anything */
			kprintf("simplify_symbols: Absolute symbol: 0x%08lx\n",
				(long)sym[i].st_value);
			break;
		case SHN_UNDEF:
			ksym =
			    resolve_symbol(sechdrs, versindex,
					   strtab + sym[i].st_name, mod);
			/* Ok if resolved.  */
			if (ksym) {
				sym[i].st_value = ksym->value;
				break;
			}
			/* Ok if weak. */
			if (ELF_ST_BIND(sym[i].st_info) == STB_WEAK)
				break;
			kprintf("simplify_symbols: Unknown symbol %s\n",
				strtab + sym[i].st_name);
			ret = -1;
			break;
		default:
			if (sym[i].st_shndx == pcpuindex)
				secbase = (unsigned long)mod->percpu;
			else
				secbase = sechdrs[sym[i].st_shndx].sh_addr;
			sym[i].st_value += secbase;
			break;
		}
	}
	return ret;
}
예제 #9
0
int
str_to_sid(void *handle, const char *name, struct cifs_sid *sid)
{
	int (*entry)(void *, const char *, struct cifs_sid *);

	*(void **)(&entry) = resolve_symbol("cifs_idmap_str_to_sid");
	if (!entry) {
		plugin_errmsg = "cifs_idmap_str_to_sid not implemented";
		return -ENOSYS;
	}

	return (*entry)(handle, name, sid);
}
예제 #10
0
int
sid_to_str(void *handle, const struct cifs_sid *sid, char **name)
{
	int (*entry)(void *, const struct cifs_sid *, char **);

	*(void **)(&entry) = resolve_symbol("cifs_idmap_sid_to_str");
	if (!entry) {
		plugin_errmsg = "cifs_idmap_sid_to_str not implemented";
		return -ENOSYS;
	}

	return (*entry)(handle, sid, name);
}
예제 #11
0
파일: linktest.c 프로젝트: lynxed/linktest
int main(int argc, char** argv)
{
    load_library(library_name);

    void (*selfloaded_func)() = resolve_symbol(library_name, function_name);
    if (!selfloaded_func)
    {
        fprintf(stderr, "failed to locate %s()\n", function_name);
        return 1;
    }

    fprintf(stderr, "calling %s() by programically located pointer:\n", function_name);
    selfloaded_func();
}
예제 #12
0
int
ids_to_sids(void *handle, const struct cifs_uxid *cuxid, const size_t num,
		struct cifs_sid *sid)
{
	int (*entry)(void *handle, const struct cifs_uxid *cuxid,
			const size_t num, struct cifs_sid *sid);

	*(void **)(&entry) = resolve_symbol("cifs_idmap_ids_to_sids");
	if (!entry) {
		plugin_errmsg = "cifs_idmap_ids_to_sids not implemented";
		return -ENOSYS;
	}

	return (*entry)(handle, cuxid, num, sid);
}
예제 #13
0
int
init_plugin(void **handle)
{
	int ret;
	int (*init)(void **, const char **);

	ret = open_plugin();
	if (ret)
		return ret;

	init = resolve_symbol("cifs_idmap_init_plugin");
	if (!init) {
		plugin_errmsg = "cifs_idmap_init_plugin not implemented";
		return -ENOSYS;
	}
	return (*init)(handle, &plugin_errmsg);
}
예제 #14
0
void symbol_dump_resolved(int level, const char *symbol)
{
    int has_value;
    i32 value;

    if(resolve_symbol(symbol, &has_value, &value))
    {
        if(has_value)
        {
            LOG(level, ("symbol \"%s\" resolves to %d ($%04X)\n",
                        symbol, value, value));
        }
        else
        {
            LOG(level, ("symbol \"%s\" is defined but has no value\n",
                        symbol));
        }
    }
    else
    {
        LOG(level, ("symbol \"%s\" not found\n", symbol));
    }
}
예제 #15
0
uint32_t start_app(uint32_t from, const wchar_t *path,
    const wchar_t *arguments, const wchar_t *curdir, uint32_t *tid,
    int show_window)
{
    create_process_t s;
    memset(&s, 0, sizeof(s));

    s.si.cb = sizeof(s.si);

    // Emulate explorer.exe's startupinfo flags behavior.
    s.si.dwFlags = STARTF_USESHOWWINDOW;
    s.si.wShowWindow = show_window;

    s.create_process_w = resolve_symbol("kernel32", "CreateProcessW");
    s.get_last_error = resolve_symbol("kernel32", "GetLastError");

    wchar_t *cmd_line =
        malloc(strsizeW(path) + strsizeW(arguments) + 4 * sizeof(wchar_t));
    wsprintfW(cmd_line, L"\"%s\" %s", path, arguments);

    s.filepath = write_data(from, path, strsizeW(path));
    s.cmdline = write_data(from, cmd_line, strsizeW(cmd_line));
    s.curdir = write_data(from, curdir, strsizeW(curdir));

    create_process_t *settings_addr = write_data(from, &s, sizeof(s));

    void *shellcode_addr = write_data(from, &create_process_worker, 0x1000);

    uint32_t last_error =
        create_thread_and_wait(from, shellcode_addr, settings_addr);
    if(last_error != 0) {
        error("[-] Error launching process: %d\n", last_error);
    }

    read_data(from, settings_addr, &s, sizeof(s));

    free_data(from, s.curdir, strsizeW(curdir));
    free_data(from, s.cmdline, strsizeW(cmd_line));
    free_data(from, s.filepath, strsizeW(path));
    free_data(from, shellcode_addr, 0x1000);
    free_data(from, settings_addr, sizeof(s));
    free(cmd_line);

    HANDLE process_handle = open_process(from), object_handle;

    if(DuplicateHandle(process_handle, s.pi.hThread, GetCurrentProcess(),
            &object_handle, DUPLICATE_SAME_ACCESS, FALSE,
            DUPLICATE_CLOSE_SOURCE) != FALSE) {
        CloseHandle(object_handle);
    }

    if(DuplicateHandle(process_handle, s.pi.hProcess, GetCurrentProcess(),
            &object_handle, DUPLICATE_SAME_ACCESS, FALSE,
            DUPLICATE_CLOSE_SOURCE) != FALSE) {
        CloseHandle(object_handle);
    }

    CloseHandle(process_handle);

    if(tid != NULL) {
        *tid = s.pi.dwThreadId;
    }
    return s.pi.dwProcessId;
}
예제 #16
0
파일: main.c 프로젝트: huku-/injectdso
/* Force the target to call `dlopen()'. Modify its registers and stack contents
 * and continue execution until a segmentation fault is caught. Return 0 on
 * success and -1 on failure.
 */
static int force_dlopen(pid_t pid, char *filename)
{
    void *linker_addr, *dlopen_off, *dlopen_addr;
    regs_t regs;
    size_t size;

    int r = -1;

    if(resolve_symbol(LINKER_PATH, DLOPEN_NAME1, &dlopen_off) != 0 &&
            resolve_symbol(LINKER_PATH, DLOPEN_NAME2, &dlopen_off) != 0 &&
            resolve_symbol(LINKER_PATH, DLOPEN_NAME3, &dlopen_off) != 0)
    {
        printf("[*] Could not resolve dlopen()\n");
        goto ret;
    }

    if((linker_addr = get_linker_addr(pid)) == NULL)
    {
        printf("[*] Linker not found in PID %d\n", pid);
        goto ret;
    }

    dlopen_addr = linker_addr + (ptrdiff_t)dlopen_off;
    printf("[*] Resolved dlopen() at %p\n", dlopen_addr);

    if(read_registers(pid, &regs) != 0)
        goto ret;

    /* Prepare `do_dlopen()' input arguments. On Android >= 7, we set the 4th
     * argument to a value that emulates `__builtin_return_address()', so that
     * our DSO is loaded in the correct namespace.
     */
    ARG0(regs) = SP(regs) + SP_OFF;
    ARG1(regs) = RTLD_NOW | RTLD_GLOBAL;
    ARG2(regs) = 0;
    ARG3(regs) = PC(regs);

    /* We set the new PC and also set LR to force the debuggee to crash. */
#if defined(__aarch64__)
    LR(regs) = 0xffffffffffffffff;
    PC(regs) = (reg_t)dlopen_addr;
#elif defined(__arm__)
    LR(regs) = 0xffffffff;
    PC(regs) = (reg_t)dlopen_addr | 1;
    CPSR(regs) |= 1 << 5;
#endif

    printf("[*] Modifying target's state\n");

    if(write_registers(pid, &regs) != 0)
        goto ret;

    size = strlen(filename) + 1;
    if(write_memory(pid, (void *)SP(regs) + SP_OFF, filename, size) != size)
        goto ret;

    printf("[*] Waiting for target to throw SIGSEGV or SIGBUS\n");

    if(resume_and_wait(pid) != 0)
        goto ret;

    r = 0;

ret:
    return r;
}
예제 #17
0
static status_t
relocate_rela(image_t* rootImage, image_t* image, Elf64_Rela* rel,
	size_t relLength, SymbolLookupCache* cache)
{
	for (size_t i = 0; i < relLength / sizeof(Elf64_Rela); i++) {
		int type = ELF64_R_TYPE(rel[i].r_info);
		int symIndex = ELF64_R_SYM(rel[i].r_info);
		Elf64_Addr symAddr = 0;
		image_t* symbolImage = NULL;

		// Resolve the symbol, if any.
		if (symIndex != 0) {
			Elf64_Sym* sym = SYMBOL(image, symIndex);

			status_t status = resolve_symbol(rootImage, image, sym, cache,
				&symAddr, &symbolImage);
			if (status != B_OK) {
				TRACE(("resolve symbol \"%s\" returned: %" B_PRId32 "\n",
					SYMNAME(image, sym), status));
				printf("resolve symbol \"%s\" returned: %" B_PRId32 "\n",
					SYMNAME(image, sym), status);
				return status;
			}
		}

		// Address of the relocation.
		Elf64_Addr relocAddr = image->regions[0].delta + rel[i].r_offset;

		// Calculate the relocation value.
		Elf64_Addr relocValue;
		switch(type) {
			case R_X86_64_NONE:
				continue;
			case R_X86_64_64:
			case R_X86_64_GLOB_DAT:
			case R_X86_64_JUMP_SLOT:
				relocValue = symAddr + rel[i].r_addend;
				break;
			case R_X86_64_PC32:
				relocValue = symAddr + rel[i].r_addend - rel[i].r_offset;
				break;
			case R_X86_64_RELATIVE:
				relocValue = image->regions[0].delta + rel[i].r_addend;
				break;
			case R_X86_64_DTPMOD64:
				relocValue = symbolImage == NULL
							? image->dso_tls_id : symbolImage->dso_tls_id;
				break;
			case R_X86_64_DTPOFF32:
			case R_X86_64_DTPOFF64:
				relocValue = symAddr;
				break;
			default:
				TRACE(("unhandled relocation type %d\n", type));
				return B_BAD_DATA;
		}

		*(Elf64_Addr *)relocAddr = relocValue;
	}

	return B_OK;
}
예제 #18
0
파일: linktest.c 프로젝트: lynxed/linktest
static void load_library(const char* filename)
{
    // Yay! Using internals of libc! Let's just cross fingers this won't change too fast :/
    void* (*__libc_dlopen_mode)(const char*, int) = resolve_symbol("libc.so.6", "__libc_dlopen_mode");
    __libc_dlopen_mode(filename, RTLD_NOW | RTLD_GLOBAL);
}
예제 #19
0
static Dwfl_Error
relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr,
		  size_t shstrndx, struct reloc_symtab_cache *reloc_symtab,
		  Elf_Scn *scn, GElf_Shdr *shdr,
		  Elf_Scn *tscn, bool debugscn, bool partial)
{
  /* First, fetch the name of the section these relocations apply to.  */
  GElf_Shdr tshdr_mem;
  GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem);
  const char *tname = elf_strptr (relocated, shstrndx, tshdr->sh_name);
  if (tname == NULL)
    return DWFL_E_LIBELF;

  if (unlikely (tshdr->sh_type == SHT_NOBITS) || unlikely (tshdr->sh_size == 0))
    /* No contents to relocate.  */
    return DWFL_E_NOERROR;

  if (debugscn && ! ebl_debugscn_p (mod->ebl, tname))
    /* This relocation section is not for a debugging section.
       Nothing to do here.  */
    return DWFL_E_NOERROR;

  /* Fetch the section data that needs the relocations applied.  */
  Elf_Data *tdata = elf_rawdata (tscn, NULL);
  if (tdata == NULL)
    return DWFL_E_LIBELF;

  /* Apply one relocation.  Returns true for any invalid data.  */
  Dwfl_Error relocate (GElf_Addr offset, const GElf_Sxword *addend,
		       int rtype, int symndx)
  {
    /* First see if this is a reloc we can handle.
       If we are skipping it, don't bother resolving the symbol.  */

    if (unlikely (rtype == 0))
      /* In some odd situations, the linker can leave R_*_NONE relocs
	 behind.  This is probably bogus ld -r behavior, but the only
	 cases it's known to appear in are harmless: DWARF data
	 referring to addresses in a section that has been discarded.
	 So we just pretend it's OK without further relocation.  */
      return DWFL_E_NOERROR;

    Elf_Type type = ebl_reloc_simple_type (mod->ebl, rtype);
    if (unlikely (type == ELF_T_NUM))
      return DWFL_E_BADRELTYPE;

    /* First, resolve the symbol to an absolute value.  */
    GElf_Addr value;

    if (symndx == STN_UNDEF)
      /* When strip removes a section symbol referring to a
	 section moved into the debuginfo file, it replaces
	 that symbol index in relocs with STN_UNDEF.  We
	 don't actually need the symbol, because those relocs
	 are always references relative to the nonallocated
	 debugging sections, which start at zero.  */
      value = 0;
    else
      {
	GElf_Sym sym;
	GElf_Word shndx;
	Dwfl_Error error = relocate_getsym (mod, relocated, reloc_symtab,
					    symndx, &sym, &shndx);
	if (unlikely (error != DWFL_E_NOERROR))
	  return error;

	if (shndx == SHN_UNDEF || shndx == SHN_COMMON)
	  {
	    /* Maybe we can figure it out anyway.  */
	    error = resolve_symbol (mod, reloc_symtab, &sym, shndx);
	    if (error != DWFL_E_NOERROR
		&& !(error == DWFL_E_RELUNDEF && shndx == SHN_COMMON))
	      return error;
	  }

	value = sym.st_value;
      }

    /* These are the types we can relocate.  */
#define TYPES		DO_TYPE (BYTE, Byte); DO_TYPE (HALF, Half);	\
    DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword);			\
    DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword)
    size_t size;
    switch (type)
      {
#define DO_TYPE(NAME, Name)			\
	case ELF_T_##NAME:			\
	  size = sizeof (GElf_##Name);		\
	break
	TYPES;
#undef DO_TYPE
      default:
	return DWFL_E_BADRELTYPE;
      }

    if (offset + size > tdata->d_size)
      return DWFL_E_BADRELOFF;

#define DO_TYPE(NAME, Name) GElf_##Name Name;
    union { TYPES; } tmpbuf;
#undef DO_TYPE
    Elf_Data tmpdata =
      {
	.d_type = type,
	.d_buf = &tmpbuf,
	.d_size = size,
	.d_version = EV_CURRENT,
      };
    Elf_Data rdata =
      {
	.d_type = type,
	.d_buf = tdata->d_buf + offset,
	.d_size = size,
	.d_version = EV_CURRENT,
      };

    /* XXX check for overflow? */
    if (addend)
      {
	/* For the addend form, we have the value already.  */
	value += *addend;
	switch (type)
	  {
#define DO_TYPE(NAME, Name)			\
	    case ELF_T_##NAME:			\
	      tmpbuf.Name = value;		\
	    break
	    TYPES;
#undef DO_TYPE
	  default:
	    abort ();
	  }
      }
    else
      {
	/* Extract the original value and apply the reloc.  */
	Elf_Data *d = gelf_xlatetom (relocated, &tmpdata, &rdata,
				     ehdr->e_ident[EI_DATA]);
	if (d == NULL)
	  return DWFL_E_LIBELF;
	assert (d == &tmpdata);
	switch (type)
	  {
#define DO_TYPE(NAME, Name)				\
	    case ELF_T_##NAME:				\
	      tmpbuf.Name += (GElf_##Name) value;	\
	    break
	    TYPES;
#undef DO_TYPE
	  default:
	    abort ();
	  }
      }

    /* Now convert the relocated datum back to the target
       format.  This will write into rdata.d_buf, which
       points into the raw section data being relocated.  */
    Elf_Data *s = gelf_xlatetof (relocated, &rdata, &tmpdata,
				 ehdr->e_ident[EI_DATA]);
    if (s == NULL)
      return DWFL_E_LIBELF;
    assert (s == &rdata);

    /* We have applied this relocation!  */
    return DWFL_E_NOERROR;
  }

  /* Fetch the relocation section and apply each reloc in it.  */
  Elf_Data *reldata = elf_getdata (scn, NULL);
  if (reldata == NULL)
    return DWFL_E_LIBELF;

  Dwfl_Error result = DWFL_E_NOERROR;
  bool first_badreltype = true;
  inline void check_badreltype (void)
  {
    if (first_badreltype)
      {
	first_badreltype = false;
	if (ebl_get_elfmachine (mod->ebl) == EM_NONE)
	  /* This might be because ebl_openbackend failed to find
	     any libebl_CPU.so library.  Diagnose that clearly.  */
	  result = DWFL_E_UNKNOWN_MACHINE;
      }
  }

  size_t nrels = shdr->sh_size / shdr->sh_entsize;
  size_t complete = 0;
  if (shdr->sh_type == SHT_REL)
    for (size_t relidx = 0; !result && relidx < nrels; ++relidx)
      {
	GElf_Rel rel_mem, *r = gelf_getrel (reldata, relidx, &rel_mem);
	if (r == NULL)
	  return DWFL_E_LIBELF;
	result = relocate (r->r_offset, NULL,
			   GELF_R_TYPE (r->r_info),
			   GELF_R_SYM (r->r_info));
	check_badreltype ();
	if (partial)
	  switch (result)
	    {
	    case DWFL_E_NOERROR:
	      /* We applied the relocation.  Elide it.  */
	      memset (&rel_mem, 0, sizeof rel_mem);
	      gelf_update_rel (reldata, relidx, &rel_mem);
	      ++complete;
	      break;
	    case DWFL_E_BADRELTYPE:
	    case DWFL_E_RELUNDEF:
	      /* We couldn't handle this relocation.  Skip it.  */
	      result = DWFL_E_NOERROR;
	      break;
	    default:
	      break;
	    }
      }
  else
    for (size_t relidx = 0; !result && relidx < nrels; ++relidx)
      {
	GElf_Rela rela_mem, *r = gelf_getrela (reldata, relidx,
					       &rela_mem);
	if (r == NULL)
	  return DWFL_E_LIBELF;
	result = relocate (r->r_offset, &r->r_addend,
			   GELF_R_TYPE (r->r_info),
			   GELF_R_SYM (r->r_info));
	check_badreltype ();
	if (partial)
	  switch (result)
	    {
	    case DWFL_E_NOERROR:
	      /* We applied the relocation.  Elide it.  */
	      memset (&rela_mem, 0, sizeof rela_mem);
	      gelf_update_rela (reldata, relidx, &rela_mem);
	      ++complete;
	      break;
	    case DWFL_E_BADRELTYPE:
	    case DWFL_E_RELUNDEF:
	      /* We couldn't handle this relocation.  Skip it.  */
	      result = DWFL_E_NOERROR;
	      break;
	    default:
	      break;
	    }
      }

  if (likely (result == DWFL_E_NOERROR))
    {
      if (!partial || complete == nrels)
	/* Mark this relocation section as being empty now that we have
	   done its work.  This affects unstrip -R, so e.g. it emits an
	   empty .rela.debug_info along with a .debug_info that has
	   already been fully relocated.  */
	nrels = 0;
      else if (complete != 0)
	{
	  /* We handled some of the relocations but not all.
	     We've zeroed out the ones we processed.
	     Now remove them from the section.  */

	  size_t next = 0;
	  if (shdr->sh_type == SHT_REL)
	    for (size_t relidx = 0; relidx < nrels; ++relidx)
	      {
		GElf_Rel rel_mem;
		GElf_Rel *r = gelf_getrel (reldata, relidx, &rel_mem);
		if (r->r_info != 0 || r->r_offset != 0)
		  {
		    if (next != relidx)
		      gelf_update_rel (reldata, next, r);
		    ++next;
		  }
	      }
	  else
	    for (size_t relidx = 0; relidx < nrels; ++relidx)
	      {
		GElf_Rela rela_mem;
		GElf_Rela *r = gelf_getrela (reldata, relidx, &rela_mem);
		if (r->r_info != 0 || r->r_offset != 0 || r->r_addend != 0)
		  {
		    if (next != relidx)
		      gelf_update_rela (reldata, next, r);
		    ++next;
		  }
	      }
	  nrels = next;
	}

      shdr->sh_size = reldata->d_size = nrels * shdr->sh_entsize;
      gelf_update_shdr (scn, shdr);
    }

  return result;
}

Dwfl_Error
internal_function
__libdwfl_relocate (Dwfl_Module *mod, Elf *debugfile, bool debug)
{
  assert (mod->e_type == ET_REL);

  GElf_Ehdr ehdr_mem;
  const GElf_Ehdr *ehdr = gelf_getehdr (debugfile, &ehdr_mem);
  if (ehdr == NULL)
    return DWFL_E_LIBELF;

  size_t d_shstrndx;
  if (elf_getshdrstrndx (debugfile, &d_shstrndx) < 0)
    return DWFL_E_LIBELF;

  RELOC_SYMTAB_CACHE (reloc_symtab);

  /* Look at each section in the debuginfo file, and process the
     relocation sections for debugging sections.  */
  Dwfl_Error result = DWFL_E_NOERROR;
  Elf_Scn *scn = NULL;
  while (result == DWFL_E_NOERROR
	 && (scn = elf_nextscn (debugfile, scn)) != NULL)
    {
      GElf_Shdr shdr_mem;
      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);

      if ((shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
	  && shdr->sh_size != 0)
	{
	  /* It's a relocation section.  */

	  Elf_Scn *tscn = elf_getscn (debugfile, shdr->sh_info);
	  if (unlikely (tscn == NULL))
	    result = DWFL_E_LIBELF;
	  else
	    result = relocate_section (mod, debugfile, ehdr, d_shstrndx,
				       &reloc_symtab, scn, shdr, tscn,
				       debug, !debug);
	}
    }

  return result;
}
예제 #20
0
static int
relocate_rel(image_t *rootImage, image_t *image, struct Elf32_Rel *rel,
	int rel_len, SymbolLookupCache* cache)
{
	int i;
	addr_t S;
	addr_t final_val;

# define P	((addr_t *)(image->regions[0].delta + rel[i].r_offset))
# define A	(*(P))
# define B	(image->regions[0].delta)

	for (i = 0; i * (int)sizeof(struct Elf32_Rel) < rel_len; i++) {
		unsigned type = ELF32_R_TYPE(rel[i].r_info);

		switch (type) {
			case R_386_32:
			case R_386_PC32:
			case R_386_GLOB_DAT:
			case R_386_JMP_SLOT:
			case R_386_GOTOFF:
			{
				struct Elf32_Sym *sym;
				status_t status;
				sym = SYMBOL(image, ELF32_R_SYM(rel[i].r_info));

				status = resolve_symbol(rootImage, image, sym, cache, &S);
				if (status < B_OK) {
					TRACE(("resolve symbol \"%s\" returned: %ld\n",
						SYMNAME(image, sym), status));
					printf("resolve symbol \"%s\" returned: %ld\n",
						SYMNAME(image, sym), status);
					return status;
				}
			}
		}
		switch (type) {
			case R_386_NONE:
				continue;
			case R_386_32:
				final_val = S + A;
				break;
			case R_386_PC32:
				final_val = S + A - (addr_t)P;
				break;
#if 0
			case R_386_GOT32:
				final_val = G + A;
				break;
			case R_386_PLT32:
				final_val = L + A - (addr_t)P;
				break;
#endif
			case R_386_COPY:
				/* what ? */
				continue;
			case R_386_GLOB_DAT:
				final_val = S;
				break;
			case R_386_JMP_SLOT:
				final_val = S;
				break;
			case R_386_RELATIVE:
				final_val = B + A;
				break;
#if 0
			case R_386_GOTOFF:
				final_val = S + A - GOT;
				break;
			case R_386_GOTPC:
				final_val = GOT + A - P;
				break;
#endif
			default:
				TRACE(("unhandled relocation type %d\n", ELF32_R_TYPE(rel[i].r_info)));
				return B_NOT_ALLOWED;
		}

		*P = final_val;
	}

# undef P
# undef A
# undef B

	return B_NO_ERROR;
}
예제 #21
0
static int
relocate_rela(image_t *rootImage, image_t *image, Elf32_Rela *rel, int rel_len,
	SymbolLookupCache* cache)
{
	int i;
	addr_t S;
	addr_t final_val;

# define P	((addr_t *)(image->regions[0].delta + rel[i].r_offset))
//# define A	(*(P))
#define A	((addr_t)rel[i].r_addend)
# define B	(image->regions[0].delta)

	for (i = 0; i * (int)sizeof(Elf32_Rel) < rel_len; i++) {
		unsigned type = ELF32_R_TYPE(rel[i].r_info);

		switch (type) {
			case R_68K_32:
			case R_68K_16:
			case R_68K_8:
			case R_68K_PC32:
			case R_68K_PC16:
			case R_68K_PC8:
			case R_68K_GLOB_DAT:
			case R_68K_JMP_SLOT:
			{
				Elf32_Sym *sym;
				status_t status;
				sym = SYMBOL(image, ELF32_R_SYM(rel[i].r_info));

				status = resolve_symbol(rootImage, image, sym, cache, &S);
				if (status < B_OK) {
					TRACE(("resolve symbol \"%s\" returned: %ld\n",
						SYMNAME(image, sym), status));
					printf("resolve symbol \"%s\" returned: %ld\n",
						SYMNAME(image, sym), status);
					return status;
				}
			}
		}
		switch (type) {
			case R_68K_NONE:
				continue;
			case R_68K_32:
				write_32(P, S + A);
				break;
			case R_68K_16:
				if (write_16_check(P, S + A))
					break;
				TRACE(("R_68K_16 overflow\n"));
				return B_BAD_DATA;

			case R_68K_8:
				if (write_8_check(P, S + A))
					break;
				TRACE(("R_68K_8 overflow\n"));
				return B_BAD_DATA;

			case R_68K_PC32:
				write_32(P, (S + A - (addr_t)P));
				break;

#if 0
			case R_68K_PC16:
				if (write_16_check(P, (S + A - P)))
					break;
				TRACE(("R_68K_PC16 overflow\n"));
				return B_BAD_DATA;

			case R_68K_PC8:
				if (write_8(P, (S + A - P)))
					break;
				TRACE(("R_68K_PC8 overflow\n"));
				return B_BAD_DATA;

			case R_68K_GOT32:
				REQUIRE_GOT;
				write_32(P, (G + A - P));
				break;

			case R_68K_GOT16:
				REQUIRE_GOT;
				if (write_16_check(P, (G + A - P)))
					break;
				TRACE(("R_68K_GOT16 overflow\n"));
				return B_BAD_DATA;

			case R_68K_GOT8:
				REQUIRE_GOT;
				if (write_8_check(P, (G + A - P)))
					break;
				TRACE(("R_68K_GOT8 overflow\n"));
				return B_BAD_DATA;

			case R_68K_GOT32O:
				REQUIRE_GOT;
				write_32(P, (G + A));
				break;

			case R_68K_GOT16O:
				REQUIRE_GOT;
				if (write_16_check(P, (G + A)))
					break;
				TRACE(("R_68K_GOT16 overflow\n"));
				return B_BAD_DATA;

			case R_68K_GOT8O:
				REQUIRE_GOT;
				if (write_8_check(P, (G + A)))
					break;
				TRACE(("R_68K_GOT8 overflow\n"));
				return B_BAD_DATA;

			case R_68K_PLT32:
				REQUIRE_PLT;
				write_32(P, (L + A - P));
				break;

			case R_68K_PLT16:
				REQUIRE_PLT;
				if (write_16_check(P, (L + A - P)))
					break;
				TRACE(("R_68K_PLT16 overflow\n"));
				return B_BAD_DATA;

			case R_68K_PLT8:
				REQUIRE_PLT;
				if (write_8_check(P, (L + A - P)))
					break;
				TRACE(("R_68K_PLT8 overflow\n"));
				return B_BAD_DATA;

			case R_68K_PLT32O:
				REQUIRE_PLT;
				write_32(P, (L + A));
				break;

			case R_68K_PLT16O:
				REQUIRE_PLT;
				if (write_16_check(P, (L + A)))
					break;
				TRACE(("R_68K_PLT16O overflow\n"));
				return B_BAD_DATA;

			case R_68K_PLT8O:
				REQUIRE_PLT;
				if (write_8_check(P, (L + A)))
					break;
				TRACE(("R_68K_PLT8O overflow\n"));
				return B_BAD_DATA;
			case R_386_GOT32:
				final_val = G + A;
				break;
			case R_386_PLT32:
				final_val = L + A - (addr_t)P;
				break;
#endif
			case R_68K_COPY:
				/* what ? */
				continue;
			case R_68K_GLOB_DAT:
				write_32(P, S/* + A*/);
				break;
			case R_68K_JMP_SLOT:
				//XXX ? write_32(P, (G + A));
				write_32(P, S);
				break;
#if 0
			case R_386_JMP_SLOT:
				write_32(P, S);
				break;
#endif
			case R_68K_RELATIVE:
				write_32(P, B + A);
				break;

#if 0
			case R_386_GOTOFF:
				final_val = S + A - GOT;
				break;
			case R_386_GOTPC:
				final_val = GOT + A - P;
				break;
#endif
			default:
				TRACE(("unhandled relocation type %d\n", ELF32_R_TYPE(rel[i].r_info)));
				return B_NOT_ALLOWED;
		}

		*P = final_val;
	}

# undef P
# undef A
# undef B

	return B_NO_ERROR;
}