Skip to content

Commit

Permalink
Add Version requirements (#14)
Browse files Browse the repository at this point in the history
* add elf_version_requirements table

Add a table that mimics .gnu.version_r which is the list of symbol versions needed by file.

* Add coverage for code coverage
  • Loading branch information
fzakaria authored Sep 25, 2023
1 parent f84208d commit b7b8241
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 1 deletion.
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,8 @@ lint: ## Run pep8, black, mypy linters.

.PHONY: test
test: ## Run pytest primarily.
pytest
pytest

.PHONY: coverage
coverage:
coverage run -m pytest
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ dev = [
"pyright >= 1.1.325",
"pytest >= 7.4.0",
"mypy >= 1.0.0",
"coverage[toml] >= 7.3",
]

[tool.setuptools_scm]
Expand Down Expand Up @@ -69,3 +70,7 @@ useLibraryCodeForTypes = true
pythonVersion = "3.10"
pythonPlatform = "Linux"
include = ["sqlelf", "tests"]

[tool.coverage.run]
omit = ["sqlelf/_version.py", "sqlelf/**/__init__.py", "tests/**/__init__.py"]
branch = true
24 changes: 24 additions & 0 deletions sqlelf/elf.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,29 @@ def symbols_generator() -> Iterator[dict[str, Any]]:
return Generator.make_generator(symbols_generator)


def make_version_requirements(binaries: list[lief.Binary]) -> Generator:
"""Create the ELF version requirements virtual table.
This should match the values found in .gnu.version_r section."""

def version_requirements_generator() -> Iterator[dict[str, Any]]:
for binary in binaries:
# super important that these accessors are pulled out of the tight loop
# as they can be costly
binary_name = binary.name
symbol_version_req = binary.symbols_version_requirement # type: ignore
for version_requirement in symbol_version_req:
file = version_requirement.name
for aux_requirement in version_requirement.get_auxiliary_symbols():
yield {
"path": binary_name,
"file": file,
"name": aux_requirement.name,
}

return Generator.make_generator(version_requirements_generator)


def symbols(binary: lief.Binary) -> Sequence[lief.ELF.Symbol]:
"""Use heuristic to either get static symbols or dynamic symbol table
Expand Down Expand Up @@ -248,6 +271,7 @@ def register_virtual_tables(
(make_sections_generator, "elf_sections"),
(make_strings_generator, "elf_strings"),
(make_symbols_generator, "raw_elf_symbols"),
(make_version_requirements, "elf_version_requirements"),
]
for factory, name in factory_and_names:
generator = factory(binaries)
Expand Down
11 changes: 11 additions & 0 deletions tests/test_sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def test_simple_binary_mocked(Command: sh.Command) -> None:


def test_simple_select_header() -> None:
# TODO(fzakaria): Figure out a better binary to be doing that we control
engine = sql.make_sql_engine([lief.parse("/bin/ls")])
result = list(engine.execute("SELECT * FROM elf_headers LIMIT 1"))
assert len(result) == 1
Expand All @@ -48,3 +49,13 @@ def test_simple_select_header() -> None:
assert "version" in result[0]
assert "machine" in result[0]
assert "entry" in result[0]


def test_simple_select_version_requirements() -> None:
# TODO(fzakaria): Figure out a better binary to be doing that we control
engine = sql.make_sql_engine([lief.parse("/bin/ls")])
result = list(engine.execute("SELECT * FROM elf_version_requirements LIMIT 1"))
assert len(result) == 1
assert "path" in result[0]
assert "file" in result[0]
assert "name" in result[0]

0 comments on commit b7b8241

Please sign in to comment.