-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathpagination.py
More file actions
101 lines (84 loc) · 2.95 KB
/
Copy pathpagination.py
File metadata and controls
101 lines (84 loc) · 2.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#!/usr/bin/env python3
# Copyright (c) 2024-2026 Elias Bachaalany
# SPDX-License-Identifier: LicenseRef-Human-Origin-Source-1.0
#
# This file is licensed under the Human-Origin Source License v1.0.
# See LICENSE.
"""pagination: demonstrate fetching every page of a paginated list RPC.
Mirrors rust/examples/pagination.rs. The Python client doesn't ship a
dedicated Paginator class — the simple loop below is the idiomatic
equivalent.
Usage: python pagination.py [host_url]
"""
from __future__ import annotations
import sys
import libghidra as ghidra
def fetch_all(call, page_size: int = 100):
"""Collect every page from a paginated list RPC.
`call(limit, offset)` should return the items vector for one page.
"""
items: list = []
offset = 0
while True:
page = call(page_size, offset)
if not page:
break
items.extend(page)
offset += len(page)
if len(page) < page_size:
break
return items
def main() -> int:
url = sys.argv[1] if len(sys.argv) >= 2 else "http://127.0.0.1:18080"
client = ghidra.connect(url)
print("=== fetch_all: all functions ===\n")
all_funcs = fetch_all(
lambda limit, offset: client.list_functions(
range_start=0, range_end=2**64 - 1, limit=limit, offset=offset
).functions
)
print(f"Total functions: {len(all_funcs)}")
for i, f in enumerate(all_funcs[:10]):
print(f" [{i:>3}] 0x{f.entry_address:x} {f.name} ({f.size} bytes)")
if len(all_funcs) > 10:
print(f" ... and {len(all_funcs) - 10} more")
print("\n=== page-by-page: symbols (page_size=25) ===\n")
page_num = 0
total_symbols = 0
offset = 0
while page_num < 5:
items = client.list_symbols(
range_start=0, range_end=2**64 - 1, limit=25, offset=offset
).symbols
if not items:
break
page_num += 1
total_symbols += len(items)
first = items[0].name if items else "?"
last = items[-1].name if items else "?"
print(
f"Page {page_num}: {len(items)} symbols "
f"(first: '{first}', last: '{last}')"
)
offset += len(items)
print("\n=== fetch_all: all function signatures ===\n")
all_sigs = fetch_all(
lambda limit, offset: client.list_function_signatures(
range_start=0, range_end=2**64 - 1, limit=limit, offset=offset
).signatures
)
print(f"Total signatures: {len(all_sigs)}")
for sig in all_sigs[:5]:
print(
f" 0x{sig.function_entry_address:x} "
f"{sig.function_name} -> {sig.prototype}"
)
if len(all_sigs) > 5:
print(f" ... and {len(all_sigs) - 5} more")
print("\n=== Summary ===")
print(f" Functions: {len(all_funcs)}")
print(f" Signatures: {len(all_sigs)}")
print(f" Symbols: {total_symbols}+ (first {page_num} pages)")
return 0
if __name__ == "__main__":
raise SystemExit(main())