aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2016-07-17 16:03:47 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2016-07-17 16:03:47 +0200
commit0f57cc9750282ce0284fe69b06f161dea2bfc8cb (patch)
tree50afd51fec2d05752cc49441ae47c40aa831cf84
parentc5e53ec8da9b11e351893742096f76e2bceb5730 (diff)
downloadelfinfo-0f57cc9750282ce0284fe69b06f161dea2bfc8cb.tar.gz
elfinfo-0f57cc9750282ce0284fe69b06f161dea2bfc8cb.tar.bz2
elfinfo-0f57cc9750282ce0284fe69b06f161dea2bfc8cb.tar.xz
elfinfo-0f57cc9750282ce0284fe69b06f161dea2bfc8cb.zip
parser/lexer:
o Support special '/DISCARD/' as NAME. o Add 'SORT' as a token. It is equivalent with SORT_BY_NAME. The new rule sort_by_name coverts both. Ld: o Don't die on unknown sections, they can be referenced before declared. Doesn't matter for this app anyway.
-rw-r--r--GnuLdLexer.g43
-rw-r--r--GnuLdParser.g418
-rw-r--r--Ld.cpp49
-rw-r--r--elfinfo.cpp11
-rw-r--r--includes/trygvis/elfinfo/Ld.h7
5 files changed, 74 insertions, 14 deletions
diff --git a/GnuLdLexer.g4 b/GnuLdLexer.g4
index 16c4a9e..eb6090f 100644
--- a/GnuLdLexer.g4
+++ b/GnuLdLexer.g4
@@ -131,6 +131,7 @@ SIZEOF_HEADERS : 'SIZEOF_HEADERS';
SIZEOF : 'SIZEOF';
SORT_BY_ALIGNMENT : 'SORT_BY_ALIGNMENT';
SORT_BY_INIT_PRIORITY : 'SORT_BY_INIT_PRIORITY';
+SORT : 'SORT';
SORT_BY_NAME : 'SORT_BY_NAME';
SORT_NONE : 'SORT_NONE';
SPECIAL : 'SPECIAL';
@@ -159,7 +160,7 @@ QUOTE : '"' -> skip, pushMode(STRING);
// | NAME # namePlain;
//NAME : [\._a-zA-Z][\._a-zA-Z0-9]*;
-NAME : [*\._a-zA-Z][*\.\/_a-zA-Z0-9]*;
+NAME : [*\._a-zA-Z][*\.\/_a-zA-Z0-9]* | '/DISCARD/';
// TODO: ld supports some really fancy expressions here, like "0101010b", "ffH", "ffx", "$Aa" etc
//INT : '0x' [0-9a-fA-F]+
diff --git a/GnuLdParser.g4 b/GnuLdParser.g4
index 36d4515..0d2bf4b 100644
--- a/GnuLdParser.g4
+++ b/GnuLdParser.g4
@@ -213,17 +213,23 @@ wildcard_name:
| QUESTION
;
+// SORT(*) and SORT_BY_NAME(*) both mean the same
+sort_by_name:
+ SORT
+ | SORT_BY_NAME
+ ;
+
wildcard_spec:
wildcard_name
| EXCLUDE_FILE LPAREN exclude_name_list RPAREN wildcard_name
- | SORT_BY_NAME LPAREN wildcard_name RPAREN
+ | sort_by_name LPAREN wildcard_name RPAREN
| SORT_BY_ALIGNMENT LPAREN wildcard_name RPAREN
| SORT_NONE LPAREN wildcard_name RPAREN
- | SORT_BY_NAME LPAREN SORT_BY_ALIGNMENT LPAREN wildcard_name RPAREN RPAREN
- | SORT_BY_NAME LPAREN SORT_BY_NAME LPAREN wildcard_name RPAREN RPAREN
- | SORT_BY_ALIGNMENT LPAREN SORT_BY_NAME LPAREN wildcard_name RPAREN RPAREN
+ | sort_by_name LPAREN SORT_BY_ALIGNMENT LPAREN wildcard_name RPAREN RPAREN
+ | sort_by_name LPAREN sort_by_name LPAREN wildcard_name RPAREN RPAREN
+ | SORT_BY_ALIGNMENT LPAREN sort_by_name LPAREN wildcard_name RPAREN RPAREN
| SORT_BY_ALIGNMENT LPAREN SORT_BY_ALIGNMENT LPAREN wildcard_name RPAREN RPAREN
- | SORT_BY_NAME LPAREN EXCLUDE_FILE LPAREN exclude_name_list RPAREN wildcard_name RPAREN
+ | sort_by_name LPAREN EXCLUDE_FILE LPAREN exclude_name_list RPAREN wildcard_name RPAREN
| SORT_BY_INIT_PRIORITY LPAREN wildcard_name RPAREN
;
@@ -265,7 +271,7 @@ statement:
| CREATE_OBJECT_SYMBOLS
| SEMICOLON
| CONSTRUCTORS
- | SORT_BY_NAME LPAREN CONSTRUCTORS RPAREN
+ | sort_by_name LPAREN CONSTRUCTORS RPAREN
| input_section_spec
| length LPAREN mustbe_exp RPAREN
| FILL LPAREN fill_exp RPAREN
diff --git a/Ld.cpp b/Ld.cpp
index a60656c..8bacaea 100644
--- a/Ld.cpp
+++ b/Ld.cpp
@@ -39,14 +39,18 @@ public:
}
virtual V get(ParseTree *const node) {
+ return _annotations.at(node);
+ }
+
+// virtual V get(ParseTree *const node) {
// try {
// cout << "node = " << node->getText() << endl;
- return _annotations.at(node);
+// return _annotations.at(node);
// } catch (std::out_of_range &e) {
// cout << "out of range: " << node->getText() << endl;
// throw e;
// }
- }
+// }
virtual void put(ParseTree *const node, V value) {
// cout << "put(" << node << ", " << value << ")" << endl;
@@ -88,7 +92,8 @@ public:
return s;
}
}
- throw out_of_range("No such section: " + name);
+ sections.emplace_back(Section{.name = name});
+ return sections[sections.size() - 1];
}
static uint64_t parseInt(const string &s) {
@@ -218,8 +223,34 @@ public:
LdScriptLoader::LdScriptLoader() : debug_(false) {
}
+class LdErrorListener : public BaseErrorListener {
+public:
+ std::vector<std::string> messages;
+
+ void syntaxError(IRecognizer *recognizer, Token *offendingSymbol, size_t line, int charPositionInLine,
+ const std::string &msg, std::exception_ptr e) override {
+ messages.push_back(msg);
+ }
+};
+
LdScript LdScriptLoader::load(std::string path) {
- ANTLRFileStream input(path);
+ std::ifstream stream(path, std::ios::binary);
+
+ if (!stream.good() || stream.eof()) {
+ return {};
+ }
+
+ string data;
+ while (!stream.eof()) {
+ char buf[1000];
+ stream.read(buf, sizeof(buf));
+ auto count = stream.gcount();
+ for (int i = 0; i < count; i++) {
+ data.push_back((char) (buf[i] & 0x7f));
+ }
+ }
+
+ ANTLRInputStream input(data);
GnuLdLexer lexer(&input);
CommonTokenStream tokens(&lexer);
tokens.fill();
@@ -233,9 +264,17 @@ LdScript LdScriptLoader::load(std::string path) {
GnuLdParser parser(&tokens);
ElfinfoGnuLdBaseListener listener;
parser.addParseListener(&listener);
+
+ LdErrorListener ldErrorListener;
+ parser.addErrorListener(&ldErrorListener);
+
auto file = parser.file();
- if (debug_) {
+ if (!ldErrorListener.messages.empty()) {
+ throw LdParseException(ldErrorListener.messages);
+ }
+
+ if (debug_ && parser.getNumberOfSyntaxErrors() == 0) {
std::cout << file->toStringTree(&parser) << std::endl << std::endl;
}
diff --git a/elfinfo.cpp b/elfinfo.cpp
index 6ddbceb..985a2de 100644
--- a/elfinfo.cpp
+++ b/elfinfo.cpp
@@ -192,10 +192,17 @@ int main(int argc, char **argv) {
LdScript file = loader.load(ld_filename);
memoryAreas.insert(memoryAreas.end(), file.memoryAreas.begin(), file.memoryAreas.end());
+ } catch (LdParseException &e) {
+ for (auto &m: e.messages) {
+ fprintf(stderr, m.c_str());
+ }
+ errx(EX_DATAERR, "Could not parse ld script");
} catch (std::exception &e) {
- errx(EX_DATAERR, "Unhandled exception when parsing LD script. The parser is new and fragile, so please file a bug and send me your LD script: %s", e.what());
+ errx(EX_DATAERR, "Unhandled exception when parsing LD script. "
+ "The parser is new and fragile, so please file a bug and send me your LD script: %s", e.what());
} catch (...) {
- errx(EX_DATAERR, "Unhandled exception when parsing LD script. The parser is new and fragile, so please file a bug and send me your LD script.");
+ errx(EX_DATAERR, "Unhandled exception when parsing LD script. "
+ "The parser is new and fragile, so please file a bug and send me your LD script.");
}
}
diff --git a/includes/trygvis/elfinfo/Ld.h b/includes/trygvis/elfinfo/Ld.h
index cab466d..09dcaec 100644
--- a/includes/trygvis/elfinfo/Ld.h
+++ b/includes/trygvis/elfinfo/Ld.h
@@ -8,6 +8,13 @@
namespace trygvis {
namespace elfinfo {
+class LdParseException : public std::runtime_error {
+public:
+ explicit LdParseException(const std::vector<std::string> messages) : runtime_error("Parse error"), messages(messages) {}
+
+ const std::vector<std::string> messages;
+};
+
enum class MemoryAttribute {
R, W, X
};