Ejemplo n.º 1
0
LibraryView* LibraryList::FindKnownLibrary(const char* name) {
  const char* base_name = GetBaseNamePtr(name);
  for (size_t n = 0; n < known_libraries_.GetCount(); ++n) {
    LibraryView* wrap = known_libraries_[n];
    if (!strcmp(base_name, wrap->GetName()))
      return wrap;
  }
  return NULL;
}
Ejemplo n.º 2
0
bool SharedLibrary::Load(const char* full_path,
                         size_t load_address,
                         size_t file_offset,
                         Error* error) {
  // First, record the path.
  LOG("%s: full path '%s'\n", __FUNCTION__, full_path);

  size_t full_path_len = strlen(full_path);
  if (full_path_len >= sizeof(full_path_)) {
    error->Format("Path too long: %s", full_path);
    return false;
  }

  strlcpy(full_path_, full_path, sizeof(full_path_));
  base_name_ = GetBaseNamePtr(full_path_);

  // Load the ELF binary in memory.
  LOG("%s: Loading ELF segments for %s\n", __FUNCTION__, base_name_);

  {
    ElfLoader loader;
    if (!loader.LoadAt(full_path_, file_offset, load_address, error)) {
      return false;
    }

    if (!view_.InitUnmapped(loader.load_start(),
                            loader.loaded_phdr(),
                            loader.phdr_count(),
                            error)) {
      return false;
    }

    if (!symbols_.Init(&view_)) {
      *error = "Missing or malformed symbol table";
      return false;
    }
  }

  if (phdr_table_get_relro_info(view_.phdr(),
                                view_.phdr_count(),
                                view_.load_bias(),
                                &relro_start_,
                                &relro_size_) < 0) {
    relro_start_ = 0;
    relro_size_ = 0;
  }

#ifdef __arm__
  LOG("%s: Extracting ARM.exidx table for %s\n", __FUNCTION__, base_name_);
  (void)phdr_table_get_arm_exidx(
      phdr(), phdr_count(), load_bias(), &arm_exidx_, &arm_exidx_count_);
#endif

  LOG("%s: Parsing dynamic table for %s\n", __FUNCTION__, base_name_);
  ElfView::DynamicIterator dyn(&view_);
  for (; dyn.HasNext(); dyn.GetNext()) {
    ELF::Addr dyn_value = dyn.GetValue();
    uintptr_t dyn_addr = dyn.GetAddress(load_bias());
    switch (dyn.GetTag()) {
      case DT_DEBUG:
        if (view_.dynamic_flags() & PF_W) {
          *dyn.GetValuePointer() =
              reinterpret_cast<uintptr_t>(Globals::GetRDebug()->GetAddress());
        }
        break;
      case DT_INIT:
        LOG("  DT_INIT addr=%p\n", dyn_addr);
        init_func_ = reinterpret_cast<linker_function_t>(dyn_addr);
        break;
      case DT_FINI:
        LOG("  DT_FINI addr=%p\n", dyn_addr);
        fini_func_ = reinterpret_cast<linker_function_t>(dyn_addr);
        break;
      case DT_INIT_ARRAY:
        LOG("  DT_INIT_ARRAY addr=%p\n", dyn_addr);
        init_array_ = reinterpret_cast<linker_function_t*>(dyn_addr);
        break;
      case DT_INIT_ARRAYSZ:
        init_array_count_ = dyn_value / sizeof(ELF::Addr);
        LOG("  DT_INIT_ARRAYSZ value=%p count=%p\n",
            dyn_value,
            init_array_count_);
        break;
      case DT_FINI_ARRAY:
        LOG("  DT_FINI_ARRAY addr=%p\n", dyn_addr);
        fini_array_ = reinterpret_cast<linker_function_t*>(dyn_addr);
        break;
      case DT_FINI_ARRAYSZ:
        fini_array_count_ = dyn_value / sizeof(ELF::Addr);
        LOG("  DT_FINI_ARRAYSZ value=%p count=%p\n",
            dyn_value,
            fini_array_count_);
        break;
      case DT_PREINIT_ARRAY:
        LOG("  DT_PREINIT_ARRAY addr=%p\n", dyn_addr);
        preinit_array_ = reinterpret_cast<linker_function_t*>(dyn_addr);
        break;
      case DT_PREINIT_ARRAYSZ:
        preinit_array_count_ = dyn_value / sizeof(ELF::Addr);
        LOG("  DT_PREINIT_ARRAYSZ value=%p count=%p\n",
            dyn_value,
            preinit_array_count_);
        break;
      case DT_SYMBOLIC:
        LOG("  DT_SYMBOLIC\n");
        has_DT_SYMBOLIC_ = true;
        break;
      case DT_FLAGS:
        if (dyn_value & DF_SYMBOLIC)
          has_DT_SYMBOLIC_ = true;
        break;
#if defined(__mips__)
      case DT_MIPS_RLD_MAP:
        *dyn.GetValuePointer() =
            reinterpret_cast<ELF::Addr>(Globals::GetRDebug()->GetAddress());
        break;
#endif
      default:
        ;
    }
  }

  LOG("%s: Load complete for %s\n", __FUNCTION__, base_name_);
  return true;
}
Ejemplo n.º 3
0
TEST(GetBaseNamePtr, Test) {
  const char kString[] = "/tmp/foo";
  EXPECT_EQ(kString + 5, GetBaseNamePtr(kString));
}
Ejemplo n.º 4
0
LibraryView* LibraryList::LoadLibrary(const char* lib_name,
                                      int dlopen_mode,
                                      uintptr_t load_address,
                                      off_t file_offset,
                                      SearchPathList* search_path_list,
                                      Error* error) {

  const char* base_name = GetBaseNamePtr(lib_name);

  LOG("%s: lib_name='%s'\n", __FUNCTION__, lib_name);

  // First check whether a library with the same base name was
  // already loaded.
  LibraryView* wrap = FindKnownLibrary(lib_name);
  if (wrap) {
    if (load_address) {
      // Check that this is a crazy library and that is was loaded at
      // the correct address.
      if (!wrap->IsCrazy()) {
        error->Format("System library can't be loaded at fixed address %08x",
                      load_address);
        return NULL;
      }
      uintptr_t actual_address = wrap->GetCrazy()->load_address();
      if (actual_address != load_address) {
        error->Format("Library already loaded at @%08x, can't load it at @%08x",
                      actual_address,
                      load_address);
        return NULL;
      }
    }
    wrap->AddRef();
    return wrap;
  }

  if (IsSystemLibrary(lib_name)) {
    // This is a system library, probably because we're loading the
    // library as a dependency.
    LOG("%s: Loading system library '%s'\n", __FUNCTION__, lib_name);
    ::dlerror();
    void* system_lib = dlopen(lib_name, dlopen_mode);
    if (!system_lib) {
      error->Format("Can't load system library %s: %s", lib_name, ::dlerror());
      return NULL;
    }

    LibraryView* wrap = new LibraryView();
    wrap->SetSystem(system_lib, lib_name);
    known_libraries_.PushBack(wrap);

    LOG("%s: System library %s loaded at %p\n", __FUNCTION__, lib_name, wrap);
    LOG("  name=%s\n", wrap->GetName());
    return wrap;
  }

  ScopedPtr<SharedLibrary> lib(new SharedLibrary());

  // Find the full library path.
  String full_path;

  if (!strchr(lib_name, '/')) {
    LOG("%s: Looking through the search path list\n", __FUNCTION__);
    const char* path = search_path_list->FindFile(lib_name);
    if (!path) {
      error->Format("Can't find library file %s", lib_name);
      return NULL;
    }
    full_path = path;
  } else {
    if (lib_name[0] != '/') {
      // Need to transform this into a full path.
      full_path = GetCurrentDirectory();
      if (full_path.size() && full_path[full_path.size() - 1] != '/')
        full_path += '/';
      full_path += lib_name;
    } else {
      // Absolute path. Easy.
      full_path = lib_name;
    }
    LOG("%s: Full library path: %s\n", __FUNCTION__, full_path.c_str());
    if (!PathIsFile(full_path.c_str())) {
      error->Format("Library file doesn't exist: %s", full_path.c_str());
      return NULL;
    }
  }

  // Load the library
  if (!lib->Load(full_path.c_str(), load_address, file_offset, error))
    return NULL;

  // Load all dependendent libraries.
  LOG("%s: Loading dependencies of %s\n", __FUNCTION__, base_name);
  SharedLibrary::DependencyIterator iter(lib.Get());
  Vector<LibraryView*> dependencies;
  while (iter.GetNext()) {
    Error dep_error;
    LibraryView* dependency = LoadLibrary(iter.GetName(),
                                          dlopen_mode,
                                          0U /* load address */,
                                          0U /* file offset */,
                                          search_path_list,
                                          &dep_error);
    if (!dependency) {
      error->Format("When loading %s: %s", base_name, dep_error.c_str());
      return NULL;
    }
    dependencies.PushBack(dependency);
  }
  if (CRAZY_DEBUG) {
    LOG("%s: Dependencies loaded for %s\n", __FUNCTION__, base_name);
    for (size_t n = 0; n < dependencies.GetCount(); ++n)
      LOG("  ... %p %s\n", dependencies[n], dependencies[n]->GetName());
    LOG("    dependencies @%p\n", &dependencies);
  }

  // Relocate the library.
  LOG("%s: Relocating %s\n", __FUNCTION__, base_name);
  if (!lib->Relocate(this, &dependencies, error))
    return NULL;

  // Notify GDB of load.
  lib->link_map_.l_addr = lib->load_address();
  lib->link_map_.l_name = const_cast<char*>(lib->base_name_);
  lib->link_map_.l_ld = reinterpret_cast<uintptr_t>(lib->view_.dynamic());
  Globals::GetRDebug()->AddEntry(&lib->link_map_);

  // The library was properly loaded, add it to the list of crazy
  // libraries. IMPORTANT: Do this _before_ calling the constructors
  // because these could call dlopen().
  lib->list_next_ = head_;
  lib->list_prev_ = NULL;
  if (head_)
    head_->list_prev_ = lib.Get();
  head_ = lib.Get();

  // Then create a new LibraryView for it.
  wrap = new LibraryView();
  wrap->SetCrazy(lib.Get(), lib_name);
  known_libraries_.PushBack(wrap);

  LOG("%s: Running constructors for %s\n", __FUNCTION__, base_name);

  // Now run the constructors.
  lib->CallConstructors();

  LOG("%s: Done loading %s\n", __FUNCTION__, base_name);
  lib.Release();

  return wrap;
}