blob: 16cc1215e7f0e68ac93c1e3127e7b4eca23c442a [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CRAZY_LINKER_SEARCH_PATH_LIST_H
#define CRAZY_LINKER_SEARCH_PATH_LIST_H
#include <stdint.h>
#include <string.h>
#include "crazy_linker_util.h" // for String
namespace crazy {
// A simple class to model a list of search paths, and perform
// file system probing with it.
class SearchPathList {
public:
SearchPathList() = default;
// Reset the list, i.e. make it empty.
void Reset();
// Reset the list from an environment variable value.
void ResetFromEnv(const char* var_name);
// Add one or more paths to the list.
// |path_list| contains a list of paths separated by columns.
// |path_list_end| points after the list's last character.
//
// NOTE: Adding a zip archive to the list is supported by using an
// exclamation mark as a delimiter inside a path. For example, the value
// '/path/to/archive.zip!lib/armeabi-v7a', means looking for libraries
// inside the zip archive at '/path/to/archive.zip', that are stored
// as 'lib/armeabi-v7a/<libname>', or even 'lib/armeabi-v7a/crazy.<libname>'.
// Read the documentation for FindFile() below for more details.
void AddPaths(const char* path_list, const char* path_list_end);
// Convenience function that takes a 0-terminated string.
void AddPaths(const char* path_list) {
AddPaths(path_list, path_list + ::strlen(path_list));
}
// The result of FindFile() below.
// |path| is the path to the file containing the library, or nullptr on error.
// |offset| is the byte offset within |path| where the library is located.
struct Result {
String path;
int32_t offset = 0;
// Returns true iff this instance matches a valid file and offset.
inline bool IsValid() const { return !path.IsEmpty(); }
};
// Try to find a library file named |file_name| by probing the directories
// added through AddPaths(). This returns a (path, offset) tuple where
// |path| corresponds to the file path to load the library from, and
// |offset| to its offset inside the file. This allows loading libraries
// directly from zip archives, when they are uncompressed and page-aligned
// within them.
//
// In case of failure, the path will be empty, and the offset will be 0.
//
// Note that if |file_name| does not contain any directory separator or
// exclamation name, the corresponding file will be searched in the list
// of paths added through AddPaths(). Otherwise, this is considered a direct
// file path and the search list will be ignored.
//
// File paths, either given directly by |file_name| or created by prepending
// search list items to it, can contain an exclamation mark to indicate that
// the library should be looked into a zip archive. For a concrete example
// 'path/to/archive.zip!libs/libfoo.so' will look into the zip archive
// at 'path/to/archive.zip' for a file within it named 'libs/libfoo.so'.
//
// This matches the behaviour of the Android system linker, starting with M
// (i.e. API level 23), but can be used on previous Android releases too.
//
// Said libraries must be uncompressed and page-aligned for the linker
// to later be able to load them properly.
//
// NOTE: It is also possible to store library files with a 'crazy.' prefix
// inside zip archives. In the following example, the function will first
// look for 'libs/libfoo.so', and if not found, will also look for a file
// named 'libs/crazy.libfoo.so'.
//
// Using such a prefix is useful on Android: such libraries can still be
// loaded directly from the APK, but will not be extracted by the system
// at installation into the application data directory (at least before
// Android M). Note that said libraries should simply be renamed within
// the zip file (i.e. they should still use the same internal DT_SONAME
// of 'libfoo.so' for the linker to work properly).
//
Result FindFile(const char* file_name) const;
private:
String list_;
String env_list_;
};
} // namespace crazy
#endif // CRAZY_LINKER_SEARCH_PATH_LIST_H