Skip to content

Commit

Permalink
add linker script parser
Browse files Browse the repository at this point in the history
  • Loading branch information
DennyDai committed Mar 3, 2024
1 parent 2adcdda commit 4becb32
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 0 deletions.
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ dependencies = [
"angr",
"pyelftools",
"pypcode",
"lark",
"lief",
"keystone-engine",
"intelhex",
Expand Down
41 changes: 41 additions & 0 deletions src/patcherex2/components/utils/linker_script.lark
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
start: (memoryblock | sectionblock | OHTERBLOCK)*

memoryblock: "MEMORY" "{" memory_def* "}"
memory_def: memory_name ["(" memory_attr ")"] ":" "ORIGIN" "=" memory_origin "," "LENGTH" "=" memory_length
memory_attr: CNAME
memory_name: CNAME
memory_origin: HEX | INT
memory_length: HEX | INT | SIZE

sectionblock: "SECTIONS" "{" section_stmt* "}"
section_stmt: section_def | IGNORE_ASSN
section_def: section_name section_addr? ":" IGNORE_BRACE section_region? section_lma_region?
section_addr: HEX | INT
section_name: SECTION_NAME
section_region: ">" CNAME
section_lma_region: "AT>" CNAME

OHTERBLOCK: IGNORE_STMT

IGNORE_PAREN: "(" /[^\(\)]+/s ")"
IGNORE_BRACE: "{" /[^\{\}]+/s "}"
IGNORE_ASSN: /[^=;]+/s "=" /[^=;]+/s ";"
IGNORE_STMT: ("_"|UCASE_LETTER) ("_"|UCASE_LETTER|DIGIT)* (IGNORE_BRACE | IGNORE_PAREN)

SECTION_NAME: "." ("."|CNAME)* "*"?
SIZE: INT ["K" | "M" | "G"]
HEX: "0x" HEXDIGIT+

%import common.LETTER
%import common.UCASE_LETTER
%import common.CNAME
%import common.HEXDIGIT
%import common.DIGIT
%import common.WS
%import common.INT
%import common.CPP_COMMENT
%import common.C_COMMENT

%ignore CPP_COMMENT
%ignore C_COMMENT
%ignore WS
53 changes: 53 additions & 0 deletions src/patcherex2/components/utils/linker_script_parser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import os

import lark


class LinkerScriptParser:
def __init__(self, linker_script_content: str) -> None:
self.linker_script_content = linker_script_content
self.ast = self._parse()

@staticmethod
def from_file(linker_script_path: str):
with open(linker_script_path) as f:
return LinkerScriptParser(f.read())

@staticmethod
def from_string(linker_script_content: str):
return LinkerScriptParser(linker_script_content)

def _parse(self):
with open(os.path.join(os.path.dirname(__file__), "linker_script.lark")) as f:
parser = lark.Lark(f.read())
return parser.parse(self.linker_script_content)

def _get_ast_data(self, tree, name):
node = next(tree.find_data(name), None)
return node.children[0].value if node else None

def get_memory_regions(self):
memory_regions = []
for mem_def in self.ast.find_data("memory_def"):
memory_regions.append(
{
"name": self._get_ast_data(mem_def, "memory_name"),
"attr": self._get_ast_data(mem_def, "memory_attr"),
"origin": self._get_ast_data(mem_def, "memory_origin"),
"length": self._get_ast_data(mem_def, "memory_length"),
}
)
return memory_regions

def get_sections(self):
sections = []
for section_def in self.ast.find_data("section_def"):
sections.append(
{
"name": self._get_ast_data(section_def, "section_name"),
"addr": self._get_ast_data(section_def, "section_addr"),
"region": self._get_ast_data(section_def, "section_region"),
"lma_region": self._get_ast_data(section_def, "section_lma_region"),
}
)
return sections

0 comments on commit 4becb32

Please sign in to comment.