From 0f57cc9750282ce0284fe69b06f161dea2bfc8cb Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Sun, 17 Jul 2016 16:03:47 +0200 Subject: 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. --- GnuLdLexer.g4 | 3 ++- GnuLdParser.g4 | 18 ++++++++++------ Ld.cpp | 49 ++++++++++++++++++++++++++++++++++++++----- elfinfo.cpp | 11 ++++++++-- includes/trygvis/elfinfo/Ld.h | 7 +++++++ 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 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 messages) : runtime_error("Parse error"), messages(messages) {} + + const std::vector messages; +}; + enum class MemoryAttribute { R, W, X }; -- cgit v1.2.3