1
1
mirror of https://github.com/rui314/mold.git synced 2024-09-22 18:40:59 +03:00
mold/linker_script.cc

171 lines
4.5 KiB
C++
Raw Normal View History

2020-11-19 03:24:10 +03:00
#include "mold.h"
2020-12-13 16:10:17 +03:00
static thread_local std::string script_dir;
2020-11-19 13:31:13 +03:00
2020-12-10 07:44:58 +03:00
static std::vector<std::string_view> tokenize(std::string_view input) {
std::vector<std::string_view> vec;
2020-11-19 03:24:10 +03:00
while (!input.empty()) {
if (input[0] == ' ' || input[0] == '\t' || input[0] == '\n') {
input = input.substr(1);
continue;
}
2020-12-10 07:44:58 +03:00
if (input.starts_with("/*")) {
2020-11-19 03:24:10 +03:00
int pos = input.find("*/", 2);
2020-12-10 07:44:58 +03:00
if (pos == std::string_view::npos)
2020-11-19 03:24:10 +03:00
error("unclosed comment");
input = input.substr(pos + 2);
continue;
}
2020-12-07 14:24:12 +03:00
if (input[0] == '#') {
int pos = input.find("\n", 1);
2020-12-10 07:44:58 +03:00
if (pos == std::string_view::npos)
2020-12-07 14:24:12 +03:00
break;
input = input.substr(pos + 1);
continue;
}
2020-11-19 03:24:10 +03:00
if (input[0] == '"') {
int pos = input.find('"', 1);
2020-12-10 07:44:58 +03:00
if (pos == std::string_view::npos)
2020-11-19 03:24:10 +03:00
error("unclosed string literal");
vec.push_back(input.substr(0, pos));
input = input.substr(pos);
continue;
}
int pos = input.find_first_not_of(
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
"0123456789_.$/\\~=+[]*?-!^:");
if (pos == 0)
pos = 1;
vec.push_back(input.substr(0, pos));
input = input.substr(pos);
}
return vec;
}
2020-12-10 08:32:42 +03:00
static std::span<std::string_view>
skip(std::span<std::string_view> tok, std::string_view str) {
2020-11-19 03:24:10 +03:00
if (tok.empty() || tok[0] != str)
2020-12-10 08:32:42 +03:00
error("expected '" + std::string(str) + "'");
2020-12-10 06:54:10 +03:00
return tok.subspan(1);
2020-11-19 03:24:10 +03:00
}
2020-12-10 07:44:58 +03:00
static std::span<std::string_view> read_output_format(std::span<std::string_view> tok) {
2020-11-19 03:24:10 +03:00
tok = skip(tok, "(");
while (!tok.empty() && tok[0] != ")")
2020-12-10 06:54:10 +03:00
tok = tok.subspan(1);
2020-11-19 03:24:10 +03:00
if (tok.empty())
error("expected ')'");
2020-12-10 06:54:10 +03:00
return tok.subspan(1);
2020-11-19 03:24:10 +03:00
}
2020-12-10 08:27:38 +03:00
static MemoryMappedFile resolve_path(std::string str) {
2020-12-10 07:44:58 +03:00
if (str.starts_with("/"))
2020-11-20 14:07:33 +03:00
return must_open_input_file(config.sysroot + str);
2020-12-10 07:44:58 +03:00
if (str.starts_with("-l"))
2020-11-19 13:31:13 +03:00
return find_library(str.substr(2));
2020-12-11 03:17:43 +03:00
if (MemoryMappedFile *mb = open_input_file(script_dir + "/" + str))
return *mb;
2020-12-10 08:27:38 +03:00
if (MemoryMappedFile *mb = open_input_file(str))
2020-11-20 14:07:33 +03:00
return *mb;
2020-12-10 07:44:58 +03:00
for (std::string &dir : config.library_paths) {
std::string root = dir.starts_with("/") ? config.sysroot : "";
2020-12-10 08:27:38 +03:00
if (MemoryMappedFile *mb = open_input_file(root + dir + "/" + str))
2020-11-20 14:07:33 +03:00
return *mb;
2020-11-20 13:33:40 +03:00
}
2020-11-19 13:31:13 +03:00
error("library not found: " + str);
}
2020-12-10 07:44:58 +03:00
static std::span<std::string_view> read_group(std::span<std::string_view> tok) {
2020-11-19 03:24:10 +03:00
tok = skip(tok, "(");
while (!tok.empty() && tok[0] != ")") {
if (tok[0] == "AS_NEEDED") {
2020-11-30 10:43:47 +03:00
bool orig = config.as_needed;
2020-12-10 06:54:10 +03:00
tok = read_group(tok.subspan(1));
2020-11-30 10:43:47 +03:00
config.as_needed = orig;
2020-11-19 03:24:10 +03:00
continue;
}
2020-12-10 07:44:58 +03:00
read_file(resolve_path(std::string(tok[0])));
2020-12-10 06:54:10 +03:00
tok = tok.subspan(1);
2020-11-19 03:24:10 +03:00
}
if (tok.empty())
error("expected ')'");
2020-12-10 06:54:10 +03:00
return tok.subspan(1);
2020-11-19 03:24:10 +03:00
}
2020-12-10 08:47:19 +03:00
void parse_linker_script(MemoryMappedFile mb) {
script_dir = mb.name.substr(0, mb.name.find_last_of('/'));
2020-11-19 13:31:13 +03:00
2020-12-10 11:44:30 +03:00
std::vector<std::string_view> vec = tokenize({(char *)mb.data, mb.size});
2020-12-10 07:44:58 +03:00
std::span<std::string_view> tok = vec;
2020-11-19 03:24:10 +03:00
while (!tok.empty()) {
if (tok[0] == "OUTPUT_FORMAT")
2020-12-10 06:54:10 +03:00
tok = read_output_format(tok.subspan(1));
2020-11-30 12:06:36 +03:00
else if (tok[0] == "INPUT" || tok[0] == "GROUP")
2020-12-10 06:54:10 +03:00
tok = read_group(tok.subspan(1));
2020-11-19 03:24:10 +03:00
else
2020-12-10 08:47:19 +03:00
error(mb.name + ": unknown token: " + std::string(tok[0]));
2020-11-19 03:24:10 +03:00
}
}
2020-12-07 13:54:07 +03:00
2020-12-10 07:44:58 +03:00
void parse_version_script(std::string path) {
2020-12-07 13:54:07 +03:00
script_dir = path.substr(0, path.find_last_of('/'));
2020-12-10 08:27:38 +03:00
MemoryMappedFile mb = must_open_input_file(path);
2020-12-10 11:44:30 +03:00
std::vector<std::string_view> vec = tokenize({(char *)mb.data, mb.size});
2020-12-10 07:44:58 +03:00
std::span<std::string_view> tok = vec;
2020-12-07 13:54:07 +03:00
tok = skip(tok, "{");
2020-12-10 07:44:58 +03:00
std::vector<std::string> locals;
std::vector<std::string> globals;
std::vector<std::string> *cur = &locals;
2020-12-07 13:54:07 +03:00
2020-12-07 14:04:44 +03:00
while (!tok.empty() && tok[0] != "}") {
2020-12-07 13:54:07 +03:00
if (tok[0] == "local:") {
2020-12-07 16:13:42 +03:00
cur = &locals;
2020-12-10 06:54:10 +03:00
tok = tok.subspan(1);
2020-12-07 13:54:07 +03:00
continue;
}
if (tok.size() >= 2 && tok[0] == "local" && tok[1] == ":") {
2020-12-07 16:13:42 +03:00
cur = &locals;
2020-12-10 06:54:10 +03:00
tok = tok.subspan(2);
2020-12-07 13:54:07 +03:00
continue;
}
if (tok[0] == "global:") {
2020-12-07 16:13:42 +03:00
cur = &globals;
2020-12-10 06:54:10 +03:00
tok = tok.subspan(1);
2020-12-07 13:54:07 +03:00
continue;
}
if (tok.size() >= 2 && tok[0] == "global" && tok[1] == ":") {
2020-12-07 16:13:42 +03:00
cur = &globals;
2020-12-10 06:54:10 +03:00
tok = tok.subspan(2);
2020-12-07 13:54:07 +03:00
continue;
}
2020-12-10 07:44:58 +03:00
cur->push_back(std::string(tok[0]));
2020-12-10 06:54:10 +03:00
tok = skip(tok.subspan(1), ";");
2020-12-07 13:54:07 +03:00
}
tok = skip(tok, "}");
2020-12-07 14:04:44 +03:00
tok = skip(tok, ";");
2020-12-07 13:54:07 +03:00
if (!tok.empty())
2020-12-10 07:44:58 +03:00
error(path + ": trailing garbage token: " + std::string(tok[0]));
2020-12-07 16:13:42 +03:00
if (locals.size() != 1 || locals[0] != "*")
error(path + ": unsupported version script");
config.export_dynamic = false;
config.globals = globals;
2020-12-07 13:54:07 +03:00
}