-
Notifications
You must be signed in to change notification settings - Fork 93
.importsym #224
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
.importsym #224
Changes from all commits
760e23c
305008f
f67c48a
72d306c
6fe5f4c
24b3a0b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -562,3 +562,162 @@ void DirectiveObjImport::writeSymData(SymbolData& symData) const | |
|
|
||
| rel.writeSymbols(symData); | ||
| } | ||
|
|
||
| // | ||
| // CDirectiveSymImport | ||
| // | ||
| std::string trimSymFileLine(std::string line) | ||
| { | ||
| // Trim start of line | ||
| size_t lineStart = line.find_first_not_of(" \t"); | ||
|
|
||
| // End line at comment (starting with ;) | ||
| // \x1A included here as well since No$gba .sym file ends with it | ||
| size_t lineEnd = line.find_first_of(";\x1A"); | ||
|
|
||
| if (lineStart >= lineEnd) | ||
| return std::string(); // line consists of only whitespace | ||
|
|
||
| // Trim end of line | ||
| lineEnd = line.find_last_not_of(" \t",lineEnd-1); | ||
| // lineEnd now points to position of last char | ||
| return line.substr(lineStart,lineEnd-lineStart+1); | ||
| } | ||
|
|
||
| CDirectiveSymImport::CDirectiveSymImport(const fs::path& fileName) | ||
| { | ||
| // We may be adding global labels, so start a new section | ||
| updateSection(++Global.Section); | ||
|
|
||
| this->fileName = getFullPathName(fileName); | ||
| if (!fs::exists(this->fileName)) | ||
| { | ||
| Logger::printError(Logger::FatalError,"File %s not found",this->fileName.u8string()); | ||
| return; | ||
| } | ||
|
|
||
| TextFile file; | ||
| file.open(this->fileName,TextFile::Read); | ||
| if (!file.isOpen()) | ||
| { | ||
| Logger::printError(Logger::FatalError,"Could not open file %s",this->fileName.u8string()); | ||
| return; | ||
| } | ||
|
|
||
| std::vector<std::string> lines = file.readAll(); | ||
| size_t l = 0; | ||
| for (std::string line: lines) | ||
| { | ||
| l++; | ||
| line = trimSymFileLine(line); | ||
| if (line.empty()) | ||
| continue; | ||
|
|
||
| // Parse symbol address | ||
| const char* addrStart = (char*)line.c_str(); | ||
| char* addrEnd; | ||
| uint32_t symAddr = strtoul(addrStart,&addrEnd,16); | ||
| // Check: not 8 chars, not followed by space/tab | ||
| if (addrStart+8 != addrEnd || !strchr(" \t",*addrEnd)) | ||
| { | ||
| Logger::printError(Logger::Warning,"Invalid symbol address on line %i of symbols file %s",l,this->fileName); | ||
| continue; | ||
| } | ||
|
|
||
| // Rest of the line is the symbol value | ||
| std::string symVal = std::string(addrEnd); | ||
| symVal = symVal.substr(symVal.find_first_not_of(" \t")); | ||
|
|
||
| std::string name = symVal; | ||
|
|
||
| // Get optional label size | ||
| size_t commaPos = symVal.find(','); | ||
| uint32_t funcSize = 0; | ||
| if (commaPos != std::string::npos) | ||
| { | ||
| // Parse size | ||
| const char* sizeStart = symVal.c_str()+commaPos+1; | ||
| char* sizeEnd; | ||
| funcSize = strtoul(sizeStart,&sizeEnd,16); | ||
| // Check: empty size, not in range, not followed by eol/space/tab/comma | ||
| if (sizeStart == sizeEnd || errno == ERANGE || !strchr("\0 \t,",*sizeEnd)) | ||
| { | ||
| Logger::printError(Logger::Warning,"Invalid function size on line %i of symbols file %s",l,this->fileName); | ||
| funcSize = 0; | ||
| // We can still salvage this I guess | ||
| } | ||
| else { | ||
| // Got valid label size, so remove it from identifier (trim end in the process) | ||
| name = symVal.substr(0,symVal.find_first_of(" \t")); | ||
| } | ||
| } | ||
|
|
||
| // Create label for this symbol, if it's not a directive and it would be a global label | ||
| const Identifier identifier = Identifier(name); | ||
| if (name.find('.') != 0 && Global.symbolTable.isGlobalSymbol(identifier)) | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Symbols can contain periods (see This would make the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should still prohibit symbols starting with a period. Not all symfile directives use colons; e.g. |
||
| { | ||
| std::shared_ptr<Label> label = Global.symbolTable.getLabel(identifier,-1,-1); | ||
| if (label == nullptr) | ||
| { | ||
| // No$gba (supposedly...) allows pretty much any character, but armips doesn't | ||
| // We can't import this label, but if the user never references it, it's fine | ||
| // (If it IS referenced, that will eventually yield an error anyway) | ||
| Logger::printError(Logger::Warning,"Invalid label name \"%s\" on line %i of symbols file %s",name,l,this->fileName); | ||
| continue; | ||
| } | ||
| if (label->isDefined()) | ||
| { | ||
| Logger::printError(Logger::Error,"Label \"%s\" already defined on line %i of symbols file %s",name,l,this->fileName); | ||
| continue; | ||
| } | ||
| // If already defined and not a global symbol, that's fine, we are in a dedicated section anyway | ||
| label->setOriginalName(identifier); | ||
| label->setValue(symAddr); | ||
| label->setInfo(funcSize); | ||
| label->setUpdateInfo(false); | ||
| label->setDefined(true); | ||
|
|
||
| labels.push_back(label); | ||
| } else { | ||
| // Store the symbol anyway since we want to merge everything into the output symfile | ||
| otherSymbols.push_back(std::pair(symAddr,symVal)); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| bool CDirectiveSymImport::Validate(const ValidateState& state) | ||
| { | ||
| return false; | ||
| } | ||
|
|
||
| void CDirectiveSymImport::Encode() const | ||
| { | ||
|
|
||
| } | ||
|
|
||
| void CDirectiveSymImport::writeTempData(TempData& tempData) const | ||
| { | ||
| tempData.writeLine(-1,tfm::format(".importsym \"%s\"",fileName.u8string())); | ||
| for (const auto& label: labels) | ||
| { | ||
| tempData.writeLine(label->getValue(),tfm::format("%s",label->getName())); | ||
| } | ||
| } | ||
|
|
||
| void CDirectiveSymImport::writeSymData(SymbolData& symData) const | ||
| { | ||
| for (const auto& label: labels) | ||
| { | ||
| if (label->getInfo()) | ||
| symData.startFunction(label->getValue()); | ||
|
|
||
| symData.addLabel(label->getValue(),label->getName().string()); | ||
|
|
||
| if (label->getInfo()) | ||
| symData.endFunction(label->getValue()+label->getInfo()); | ||
| } | ||
| for (const auto& symbol: otherSymbols) | ||
| { | ||
| symData.addLabel(symbol.first,symbol.second); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| output.bin | ||
| output.sym | ||
| output.txt | ||
| *.temp.txt |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| .nds | ||
| .create "output.bin",0 | ||
|
|
||
| .if defined(.pool) | ||
| .error ".pool should not be accessible here" | ||
| .endif | ||
| .if defined(@@LocalLabel) | ||
| .error "@@LocalLabel should not be accessible here" | ||
| .endif | ||
| .if defined(@StaticLabel) | ||
| .error "@StaticLabel should not be accessible here" | ||
| .endif | ||
|
|
||
| .importsym "input.sym" | ||
|
|
||
| .if defined(.pool) | ||
| .error ".pool should not be accessible here" | ||
| .endif | ||
| .if defined(@@LocalLabel) | ||
| .error "@@LocalLabel should not be accessible here" | ||
| .endif | ||
| .if defined(@StaticLabel) | ||
| .error "@StaticLabel should not be accessible here" | ||
| .endif | ||
|
|
||
| .dd ValidLabel | ||
| .dd ValidLabelWithSpaces | ||
| .dd ValidLabelWithTabs | ||
| .dd ValidLabelWithSpacesAndTabs | ||
| .dd ValidLabelWithComment | ||
| .dd Function | ||
|
|
||
| ldr r0,=0xABCDABCD | ||
| .pool | ||
|
|
||
| .org 0x12345678 | ||
| NewlyAddedLabel1: | ||
|
|
||
| .definelabel NewlyAddedLabel2, 0x87654321 | ||
|
|
||
| .skip 4 | ||
| @NewlyAddedStaticLabel: | ||
|
|
||
| .skip 4 | ||
| @@NewlyAddedLocalLabel: | ||
|
|
||
| .close |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| 0 -sym2 output.sym SymFileImport.asm |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| 00000000 0 | ||
| 00000000 .dbl:0008 | ||
| 00000008 .dbl:0008 | ||
| 00000010 .dbl:0008 | ||
| 00000018 .dbl:0008 | ||
| 00000020 .dbl:0008 | ||
| 00000028 .dbl:0008 | ||
| 00000034 .dbl:0004 | ||
| 00000034 .pool | ||
| 004488CC Function,CC884400 | ||
| 01100110 ValidLabel | ||
| 11223344 @StaticLabel | ||
| 12345678 NewlyAddedLabel1 | ||
| 1234567C @NewlyAddedStaticLabel | ||
| 12345680 @@NewlyAddedLocalLabel | ||
| 23322332 ValidLabelWithSpaces | ||
| 45544554 ValidLabelWithTabs | ||
| 55667788 @StaticLabel | ||
| 67766776 ValidLabelWithSpacesAndTabs | ||
| 87654321 NewlyAddedLabel2 | ||
| 89988998 ValidLabelWithComment | ||
| 99AABBCC @@LocalLabel | ||
| DDEEFF00 @@LocalLabel | ||
| FEDCBA98 .pool | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| ; Line with comment | ||
|
|
||
| 01100110 ValidLabel | ||
| 23322332 ValidLabelWithSpaces | ||
| 45544554 ValidLabelWithTabs | ||
| 67766776 ValidLabelWithSpacesAndTabs | ||
| 89988998 ValidLabelWithComment ; No$gba does allow this, if there is whitespace before the ; | ||
|
|
||
| 11223344 @StaticLabel | ||
| 55667788 @StaticLabel | ||
| 99AABBCC @@LocalLabel | ||
| DDEEFF00 @@LocalLabel | ||
|
|
||
| 004488CC Function , CC884400 | ||
|
|
||
| FEDCBA98 .pool | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This works for no$gba .sym files (or
-symoutput), but not for files generated by-sym2(if.funcwas used, at least). Anything after a comma should also be removed from the identifier.