annotate lldb/examples/python/bsd.py @ 266:00f31e85ec16 default tip

Added tag current for changeset 31d058e83c98
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sat, 14 Oct 2023 10:13:55 +0900
parents 1f2b6ac9f198
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
1 #!/usr/bin/env python
150
anatofuz
parents:
diff changeset
2
anatofuz
parents:
diff changeset
3 import cmd
anatofuz
parents:
diff changeset
4 import optparse
anatofuz
parents:
diff changeset
5 import os
anatofuz
parents:
diff changeset
6 import shlex
anatofuz
parents:
diff changeset
7 import struct
anatofuz
parents:
diff changeset
8 import sys
anatofuz
parents:
diff changeset
9
anatofuz
parents:
diff changeset
10 ARMAG = "!<arch>\n"
anatofuz
parents:
diff changeset
11 SARMAG = 8
anatofuz
parents:
diff changeset
12 ARFMAG = "`\n"
anatofuz
parents:
diff changeset
13 AR_EFMT1 = "#1/"
anatofuz
parents:
diff changeset
14
anatofuz
parents:
diff changeset
15
anatofuz
parents:
diff changeset
16 def memdump(src, bytes_per_line=16, address=0):
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
17 FILTER = "".join([(len(repr(chr(x))) == 3) and chr(x) or "." for x in range(256)])
150
anatofuz
parents:
diff changeset
18 for i in range(0, len(src), bytes_per_line):
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
19 s = src[i : i + bytes_per_line]
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
20 hex_bytes = " ".join(["%02x" % (ord(x)) for x in s])
150
anatofuz
parents:
diff changeset
21 ascii = s.translate(FILTER)
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
22 print("%#08.8x: %-*s %s" % (address + i, bytes_per_line * 3, hex_bytes, ascii))
150
anatofuz
parents:
diff changeset
23
anatofuz
parents:
diff changeset
24
anatofuz
parents:
diff changeset
25 class Object(object):
anatofuz
parents:
diff changeset
26 def __init__(self, file):
anatofuz
parents:
diff changeset
27 def read_str(file, str_len):
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
28 return file.read(str_len).rstrip("\0 ")
150
anatofuz
parents:
diff changeset
29
anatofuz
parents:
diff changeset
30 def read_int(file, str_len, base):
anatofuz
parents:
diff changeset
31 return int(read_str(file, str_len), base)
anatofuz
parents:
diff changeset
32
anatofuz
parents:
diff changeset
33 self.offset = file.tell()
anatofuz
parents:
diff changeset
34 self.file = file
anatofuz
parents:
diff changeset
35 self.name = read_str(file, 16)
anatofuz
parents:
diff changeset
36 self.date = read_int(file, 12, 10)
anatofuz
parents:
diff changeset
37 self.uid = read_int(file, 6, 10)
anatofuz
parents:
diff changeset
38 self.gid = read_int(file, 6, 10)
anatofuz
parents:
diff changeset
39 self.mode = read_int(file, 8, 8)
anatofuz
parents:
diff changeset
40 self.size = read_int(file, 10, 10)
anatofuz
parents:
diff changeset
41 if file.read(2) != ARFMAG:
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
42 raise ValueError("invalid BSD object at offset %#08.8x" % (self.offset))
150
anatofuz
parents:
diff changeset
43 # If we have an extended name read it. Extended names start with
anatofuz
parents:
diff changeset
44 name_len = 0
anatofuz
parents:
diff changeset
45 if self.name.startswith(AR_EFMT1):
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
46 name_len = int(self.name[len(AR_EFMT1) :], 10)
150
anatofuz
parents:
diff changeset
47 self.name = read_str(file, name_len)
anatofuz
parents:
diff changeset
48 self.obj_offset = file.tell()
anatofuz
parents:
diff changeset
49 self.obj_size = self.size - name_len
anatofuz
parents:
diff changeset
50 file.seek(self.obj_size, 1)
anatofuz
parents:
diff changeset
51
anatofuz
parents:
diff changeset
52 def dump(self, f=sys.stdout, flat=True):
anatofuz
parents:
diff changeset
53 if flat:
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
54 f.write(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
55 "%#08.8x: %#08.8x %5u %5u %6o %#08.8x %s\n"
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
56 % (
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
57 self.offset,
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
58 self.date,
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
59 self.uid,
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
60 self.gid,
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
61 self.mode,
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
62 self.size,
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
63 self.name,
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
64 )
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
65 )
150
anatofuz
parents:
diff changeset
66 else:
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
67 f.write("%#08.8x: \n" % self.offset)
150
anatofuz
parents:
diff changeset
68 f.write(' name = "%s"\n' % self.name)
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
69 f.write(" date = %#08.8x\n" % self.date)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
70 f.write(" uid = %i\n" % self.uid)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
71 f.write(" gid = %i\n" % self.gid)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
72 f.write(" mode = %o\n" % self.mode)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
73 f.write(" size = %#08.8x\n" % (self.size))
150
anatofuz
parents:
diff changeset
74 self.file.seek(self.obj_offset, 0)
anatofuz
parents:
diff changeset
75 first_bytes = self.file.read(4)
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
76 f.write("bytes = ")
150
anatofuz
parents:
diff changeset
77 memdump(first_bytes)
anatofuz
parents:
diff changeset
78
anatofuz
parents:
diff changeset
79 def get_bytes(self):
anatofuz
parents:
diff changeset
80 saved_pos = self.file.tell()
anatofuz
parents:
diff changeset
81 self.file.seek(self.obj_offset, 0)
anatofuz
parents:
diff changeset
82 bytes = self.file.read(self.obj_size)
anatofuz
parents:
diff changeset
83 self.file.seek(saved_pos, 0)
anatofuz
parents:
diff changeset
84 return bytes
anatofuz
parents:
diff changeset
85
anatofuz
parents:
diff changeset
86 def save(self, path=None, overwrite=False):
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
87 """
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
88 Save the contents of the object to disk using 'path' argument as
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
89 the path, or save it to the current working directory using the
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
90 object name.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
91 """
150
anatofuz
parents:
diff changeset
92
anatofuz
parents:
diff changeset
93 if path is None:
anatofuz
parents:
diff changeset
94 path = self.name
anatofuz
parents:
diff changeset
95 if not overwrite and os.path.exists(path):
anatofuz
parents:
diff changeset
96 print('error: outfile "%s" already exists' % (path))
anatofuz
parents:
diff changeset
97 return
anatofuz
parents:
diff changeset
98 print('Saving "%s" to "%s"...' % (self.name, path))
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
99 with open(path, "w") as f:
150
anatofuz
parents:
diff changeset
100 f.write(self.get_bytes())
anatofuz
parents:
diff changeset
101
anatofuz
parents:
diff changeset
102
anatofuz
parents:
diff changeset
103 class StringTable(object):
anatofuz
parents:
diff changeset
104 def __init__(self, bytes):
anatofuz
parents:
diff changeset
105 self.bytes = bytes
anatofuz
parents:
diff changeset
106
anatofuz
parents:
diff changeset
107 def get_string(self, offset):
anatofuz
parents:
diff changeset
108 length = len(self.bytes)
anatofuz
parents:
diff changeset
109 if offset >= length:
anatofuz
parents:
diff changeset
110 return None
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
111 return self.bytes[offset : self.bytes.find("\0", offset)]
150
anatofuz
parents:
diff changeset
112
anatofuz
parents:
diff changeset
113
anatofuz
parents:
diff changeset
114 class Archive(object):
anatofuz
parents:
diff changeset
115 def __init__(self, path):
anatofuz
parents:
diff changeset
116 self.path = path
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
117 self.file = open(path, "r")
150
anatofuz
parents:
diff changeset
118 self.objects = []
anatofuz
parents:
diff changeset
119 self.offset_to_object = {}
anatofuz
parents:
diff changeset
120 if self.file.read(SARMAG) != ARMAG:
anatofuz
parents:
diff changeset
121 print("error: file isn't a BSD archive")
anatofuz
parents:
diff changeset
122 while True:
anatofuz
parents:
diff changeset
123 try:
anatofuz
parents:
diff changeset
124 self.objects.append(Object(self.file))
anatofuz
parents:
diff changeset
125 except ValueError:
anatofuz
parents:
diff changeset
126 break
anatofuz
parents:
diff changeset
127
anatofuz
parents:
diff changeset
128 def get_object_at_offset(self, offset):
anatofuz
parents:
diff changeset
129 if offset in self.offset_to_object:
anatofuz
parents:
diff changeset
130 return self.offset_to_object[offset]
anatofuz
parents:
diff changeset
131 for obj in self.objects:
anatofuz
parents:
diff changeset
132 if obj.offset == offset:
anatofuz
parents:
diff changeset
133 self.offset_to_object[offset] = obj
anatofuz
parents:
diff changeset
134 return obj
anatofuz
parents:
diff changeset
135 return None
anatofuz
parents:
diff changeset
136
anatofuz
parents:
diff changeset
137 def find(self, name, mtime=None, f=sys.stdout):
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
138 """
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
139 Find an object(s) by name with optional modification time. There
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
140 can be multple objects with the same name inside and possibly with
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
141 the same modification time within a BSD archive so clients must be
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
142 prepared to get multiple results.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
143 """
150
anatofuz
parents:
diff changeset
144 matches = []
anatofuz
parents:
diff changeset
145 for obj in self.objects:
anatofuz
parents:
diff changeset
146 if obj.name == name and (mtime is None or mtime == obj.date):
anatofuz
parents:
diff changeset
147 matches.append(obj)
anatofuz
parents:
diff changeset
148 return matches
anatofuz
parents:
diff changeset
149
anatofuz
parents:
diff changeset
150 @classmethod
anatofuz
parents:
diff changeset
151 def dump_header(self, f=sys.stdout):
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
152 f.write(" DATE UID GID MODE SIZE NAME\n")
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
153 f.write(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
154 " ---------- ----- ----- ------ ---------- " "--------------\n"
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
155 )
150
anatofuz
parents:
diff changeset
156
anatofuz
parents:
diff changeset
157 def get_symdef(self):
anatofuz
parents:
diff changeset
158 def get_uint32(file):
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
159 """Extract a uint32_t from the current file position."""
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
160 (v,) = struct.unpack("=I", file.read(4))
150
anatofuz
parents:
diff changeset
161 return v
anatofuz
parents:
diff changeset
162
anatofuz
parents:
diff changeset
163 for obj in self.objects:
anatofuz
parents:
diff changeset
164 symdef = []
anatofuz
parents:
diff changeset
165 if obj.name.startswith("__.SYMDEF"):
anatofuz
parents:
diff changeset
166 self.file.seek(obj.obj_offset, 0)
anatofuz
parents:
diff changeset
167 ranlib_byte_size = get_uint32(self.file)
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
168 num_ranlib_structs = ranlib_byte_size / 8
150
anatofuz
parents:
diff changeset
169 str_offset_pairs = []
anatofuz
parents:
diff changeset
170 for _ in range(num_ranlib_structs):
anatofuz
parents:
diff changeset
171 strx = get_uint32(self.file)
anatofuz
parents:
diff changeset
172 offset = get_uint32(self.file)
anatofuz
parents:
diff changeset
173 str_offset_pairs.append((strx, offset))
anatofuz
parents:
diff changeset
174 strtab_len = get_uint32(self.file)
anatofuz
parents:
diff changeset
175 strtab = StringTable(self.file.read(strtab_len))
anatofuz
parents:
diff changeset
176 for s in str_offset_pairs:
anatofuz
parents:
diff changeset
177 symdef.append((strtab.get_string(s[0]), s[1]))
anatofuz
parents:
diff changeset
178 return symdef
anatofuz
parents:
diff changeset
179
anatofuz
parents:
diff changeset
180 def get_object_dicts(self):
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
181 """
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
182 Returns an array of object dictionaries that contain they following
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
183 keys:
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
184 'object': the actual bsd.Object instance
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
185 'symdefs': an array of symbol names that the object contains
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
186 as found in the "__.SYMDEF" item in the archive
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
187 """
150
anatofuz
parents:
diff changeset
188 symdefs = self.get_symdef()
anatofuz
parents:
diff changeset
189 symdef_dict = {}
anatofuz
parents:
diff changeset
190 if symdefs:
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
191 for name, offset in symdefs:
150
anatofuz
parents:
diff changeset
192 if offset in symdef_dict:
anatofuz
parents:
diff changeset
193 object_dict = symdef_dict[offset]
anatofuz
parents:
diff changeset
194 else:
anatofuz
parents:
diff changeset
195 object_dict = {
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
196 "object": self.get_object_at_offset(offset),
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
197 "symdefs": [],
150
anatofuz
parents:
diff changeset
198 }
anatofuz
parents:
diff changeset
199 symdef_dict[offset] = object_dict
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
200 object_dict["symdefs"].append(name)
150
anatofuz
parents:
diff changeset
201 object_dicts = []
anatofuz
parents:
diff changeset
202 for offset in sorted(symdef_dict):
anatofuz
parents:
diff changeset
203 object_dicts.append(symdef_dict[offset])
anatofuz
parents:
diff changeset
204 return object_dicts
anatofuz
parents:
diff changeset
205
anatofuz
parents:
diff changeset
206 def dump(self, f=sys.stdout, flat=True):
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
207 f.write("%s:\n" % self.path)
150
anatofuz
parents:
diff changeset
208 if flat:
anatofuz
parents:
diff changeset
209 self.dump_header(f=f)
anatofuz
parents:
diff changeset
210 for obj in self.objects:
anatofuz
parents:
diff changeset
211 obj.dump(f=f, flat=flat)
anatofuz
parents:
diff changeset
212
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
213
150
anatofuz
parents:
diff changeset
214 class Interactive(cmd.Cmd):
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
215 """Interactive prompt for exploring contents of BSD archive files, type
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
216 "help" to see a list of supported commands."""
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
217
150
anatofuz
parents:
diff changeset
218 image_option_parser = None
anatofuz
parents:
diff changeset
219
anatofuz
parents:
diff changeset
220 def __init__(self, archives):
anatofuz
parents:
diff changeset
221 cmd.Cmd.__init__(self)
anatofuz
parents:
diff changeset
222 self.use_rawinput = False
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
223 self.intro = (
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
224 'Interactive BSD archive prompt, type "help" to see a '
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
225 "list of supported commands."
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
226 )
150
anatofuz
parents:
diff changeset
227 self.archives = archives
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
228 self.prompt = "% "
150
anatofuz
parents:
diff changeset
229
anatofuz
parents:
diff changeset
230 def default(self, line):
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
231 """Catch all for unknown command, which will exit the interpreter."""
150
anatofuz
parents:
diff changeset
232 print("unknown command: %s" % line)
anatofuz
parents:
diff changeset
233 return True
anatofuz
parents:
diff changeset
234
anatofuz
parents:
diff changeset
235 def do_q(self, line):
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
236 """Quit command"""
150
anatofuz
parents:
diff changeset
237 return True
anatofuz
parents:
diff changeset
238
anatofuz
parents:
diff changeset
239 def do_quit(self, line):
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
240 """Quit command"""
150
anatofuz
parents:
diff changeset
241 return True
anatofuz
parents:
diff changeset
242
anatofuz
parents:
diff changeset
243 def do_extract(self, line):
anatofuz
parents:
diff changeset
244 args = shlex.split(line)
anatofuz
parents:
diff changeset
245 if args:
anatofuz
parents:
diff changeset
246 extracted = False
anatofuz
parents:
diff changeset
247 for object_name in args:
anatofuz
parents:
diff changeset
248 for archive in self.archives:
anatofuz
parents:
diff changeset
249 matches = archive.find(object_name)
anatofuz
parents:
diff changeset
250 if matches:
anatofuz
parents:
diff changeset
251 for object in matches:
anatofuz
parents:
diff changeset
252 object.save(overwrite=False)
anatofuz
parents:
diff changeset
253 extracted = True
anatofuz
parents:
diff changeset
254 if not extracted:
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
255 print('error: no object matches "%s" in any archives' % (object_name))
150
anatofuz
parents:
diff changeset
256 else:
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
257 print("error: must specify the name of an object to extract")
150
anatofuz
parents:
diff changeset
258
anatofuz
parents:
diff changeset
259 def do_ls(self, line):
anatofuz
parents:
diff changeset
260 args = shlex.split(line)
anatofuz
parents:
diff changeset
261 if args:
anatofuz
parents:
diff changeset
262 for object_name in args:
anatofuz
parents:
diff changeset
263 for archive in self.archives:
anatofuz
parents:
diff changeset
264 matches = archive.find(object_name)
anatofuz
parents:
diff changeset
265 if matches:
anatofuz
parents:
diff changeset
266 for object in matches:
anatofuz
parents:
diff changeset
267 object.dump(flat=False)
anatofuz
parents:
diff changeset
268 else:
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
269 print(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
270 'error: no object matches "%s" in "%s"'
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
271 % (object_name, archive.path)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
272 )
150
anatofuz
parents:
diff changeset
273 else:
anatofuz
parents:
diff changeset
274 for archive in self.archives:
anatofuz
parents:
diff changeset
275 archive.dump(flat=True)
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
276 print("")
150
anatofuz
parents:
diff changeset
277
anatofuz
parents:
diff changeset
278
anatofuz
parents:
diff changeset
279 def main():
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
280 parser = optparse.OptionParser(prog="bsd", description="Utility for BSD archives")
150
anatofuz
parents:
diff changeset
281 parser.add_option(
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
282 "--object",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
283 type="string",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
284 dest="object_name",
150
anatofuz
parents:
diff changeset
285 default=None,
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
286 help=(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
287 "Specify the name of a object within the BSD archive to get "
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
288 "information on"
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
289 ),
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
290 )
150
anatofuz
parents:
diff changeset
291 parser.add_option(
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
292 "-s",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
293 "--symbol",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
294 type="string",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
295 dest="find_symbol",
150
anatofuz
parents:
diff changeset
296 default=None,
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
297 help=(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
298 "Specify the name of a symbol within the BSD archive to get "
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
299 "information on from SYMDEF"
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
300 ),
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
301 )
150
anatofuz
parents:
diff changeset
302 parser.add_option(
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
303 "--symdef",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
304 action="store_true",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
305 dest="symdef",
150
anatofuz
parents:
diff changeset
306 default=False,
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
307 help=("Dump the information in the SYMDEF."),
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
308 )
150
anatofuz
parents:
diff changeset
309 parser.add_option(
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
310 "-v",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
311 "--verbose",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
312 action="store_true",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
313 dest="verbose",
150
anatofuz
parents:
diff changeset
314 default=False,
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
315 help="Enable verbose output",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
316 )
150
anatofuz
parents:
diff changeset
317 parser.add_option(
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
318 "-e",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
319 "--extract",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
320 action="store_true",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
321 dest="extract",
150
anatofuz
parents:
diff changeset
322 default=False,
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
323 help=(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
324 "Specify this to extract the object specified with the --object "
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
325 "option. There must be only one object with a matching name or "
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
326 "the --mtime option must be specified to uniquely identify a "
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
327 "single object."
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
328 ),
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
329 )
150
anatofuz
parents:
diff changeset
330 parser.add_option(
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
331 "-m",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
332 "--mtime",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
333 type="int",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
334 dest="mtime",
150
anatofuz
parents:
diff changeset
335 default=None,
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
336 help=(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
337 "Specify the modification time of the object an object. This "
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
338 "option is used with either the --object or --extract options."
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
339 ),
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
340 )
150
anatofuz
parents:
diff changeset
341 parser.add_option(
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
342 "-o",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
343 "--outfile",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
344 type="string",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
345 dest="outfile",
150
anatofuz
parents:
diff changeset
346 default=None,
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
347 help=(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
348 "Specify a different name or path for the file to extract when "
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
349 "using the --extract option. If this option isn't specified, "
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
350 "then the extracted object file will be extracted into the "
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
351 "current working directory if a file doesn't already exist "
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
352 "with that name."
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
353 ),
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
354 )
150
anatofuz
parents:
diff changeset
355 parser.add_option(
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
356 "-i",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
357 "--interactive",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
358 action="store_true",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
359 dest="interactive",
150
anatofuz
parents:
diff changeset
360 default=False,
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
361 help=(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
362 "Enter an interactive shell that allows users to interactively "
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
363 "explore contents of .a files."
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
364 ),
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
365 )
150
anatofuz
parents:
diff changeset
366
anatofuz
parents:
diff changeset
367 (options, args) = parser.parse_args(sys.argv[1:])
anatofuz
parents:
diff changeset
368
anatofuz
parents:
diff changeset
369 if options.interactive:
anatofuz
parents:
diff changeset
370 archives = []
anatofuz
parents:
diff changeset
371 for path in args:
anatofuz
parents:
diff changeset
372 archives.append(Archive(path))
anatofuz
parents:
diff changeset
373 interpreter = Interactive(archives)
anatofuz
parents:
diff changeset
374 interpreter.cmdloop()
anatofuz
parents:
diff changeset
375 return
anatofuz
parents:
diff changeset
376
anatofuz
parents:
diff changeset
377 for path in args:
anatofuz
parents:
diff changeset
378 archive = Archive(path)
anatofuz
parents:
diff changeset
379 if options.object_name:
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
380 print("%s:\n" % (path))
150
anatofuz
parents:
diff changeset
381 matches = archive.find(options.object_name, options.mtime)
anatofuz
parents:
diff changeset
382 if matches:
anatofuz
parents:
diff changeset
383 dump_all = True
anatofuz
parents:
diff changeset
384 if options.extract:
anatofuz
parents:
diff changeset
385 if len(matches) == 1:
anatofuz
parents:
diff changeset
386 dump_all = False
anatofuz
parents:
diff changeset
387 matches[0].save(path=options.outfile, overwrite=False)
anatofuz
parents:
diff changeset
388 else:
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
389 print(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
390 'error: multiple objects match "%s". Specify '
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
391 "the modification time using --mtime."
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
392 % (options.object_name)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
393 )
150
anatofuz
parents:
diff changeset
394 if dump_all:
anatofuz
parents:
diff changeset
395 for obj in matches:
anatofuz
parents:
diff changeset
396 obj.dump(flat=False)
anatofuz
parents:
diff changeset
397 else:
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
398 print('error: object "%s" not found in archive' % (options.object_name))
150
anatofuz
parents:
diff changeset
399 elif options.find_symbol:
anatofuz
parents:
diff changeset
400 symdefs = archive.get_symdef()
anatofuz
parents:
diff changeset
401 if symdefs:
anatofuz
parents:
diff changeset
402 success = False
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
403 for name, offset in symdefs:
150
anatofuz
parents:
diff changeset
404 obj = archive.get_object_at_offset(offset)
anatofuz
parents:
diff changeset
405 if name == options.find_symbol:
anatofuz
parents:
diff changeset
406 print('Found "%s" in:' % (options.find_symbol))
anatofuz
parents:
diff changeset
407 obj.dump(flat=False)
anatofuz
parents:
diff changeset
408 success = True
anatofuz
parents:
diff changeset
409 if not success:
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
410 print('Didn\'t find "%s" in any objects' % (options.find_symbol))
150
anatofuz
parents:
diff changeset
411 else:
anatofuz
parents:
diff changeset
412 print("error: no __.SYMDEF was found")
anatofuz
parents:
diff changeset
413 elif options.symdef:
anatofuz
parents:
diff changeset
414 object_dicts = archive.get_object_dicts()
anatofuz
parents:
diff changeset
415 for object_dict in object_dicts:
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
416 object_dict["object"].dump(flat=False)
150
anatofuz
parents:
diff changeset
417 print("symbols:")
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
418 for name in object_dict["symdefs"]:
150
anatofuz
parents:
diff changeset
419 print(" %s" % (name))
anatofuz
parents:
diff changeset
420 else:
anatofuz
parents:
diff changeset
421 archive.dump(flat=not options.verbose)
anatofuz
parents:
diff changeset
422
anatofuz
parents:
diff changeset
423
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
424 if __name__ == "__main__":
150
anatofuz
parents:
diff changeset
425 main()
anatofuz
parents:
diff changeset
426
anatofuz
parents:
diff changeset
427
anatofuz
parents:
diff changeset
428 def print_mtime_error(result, dmap_mtime, actual_mtime):
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
429 print(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
430 "error: modification time in debug map (%#08.8x) doesn't "
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
431 "match the .o file modification time (%#08.8x)" % (dmap_mtime, actual_mtime),
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
432 file=result,
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
433 )
150
anatofuz
parents:
diff changeset
434
anatofuz
parents:
diff changeset
435
anatofuz
parents:
diff changeset
436 def print_file_missing_error(result, path):
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
437 print('error: file "%s" doesn\'t exist' % (path), file=result)
150
anatofuz
parents:
diff changeset
438
anatofuz
parents:
diff changeset
439
anatofuz
parents:
diff changeset
440 def print_multiple_object_matches(result, object_name, mtime, matches):
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
441 print(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
442 "error: multiple matches for object '%s' with with "
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
443 "modification time %#08.8x:" % (object_name, mtime),
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
444 file=result,
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
445 )
150
anatofuz
parents:
diff changeset
446 Archive.dump_header(f=result)
anatofuz
parents:
diff changeset
447 for match in matches:
anatofuz
parents:
diff changeset
448 match.dump(f=result, flat=True)
anatofuz
parents:
diff changeset
449
anatofuz
parents:
diff changeset
450
anatofuz
parents:
diff changeset
451 def print_archive_object_error(result, object_name, mtime, archive):
anatofuz
parents:
diff changeset
452 matches = archive.find(object_name, f=result)
anatofuz
parents:
diff changeset
453 if len(matches) > 0:
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
454 print(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
455 "error: no objects have a modification time that "
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
456 "matches %#08.8x for '%s'. Potential matches:" % (mtime, object_name),
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
457 file=result,
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
458 )
150
anatofuz
parents:
diff changeset
459 Archive.dump_header(f=result)
anatofuz
parents:
diff changeset
460 for match in matches:
anatofuz
parents:
diff changeset
461 match.dump(f=result, flat=True)
anatofuz
parents:
diff changeset
462 else:
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
463 print(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
464 'error: no object named "%s" found in archive:' % (object_name), file=result
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
465 )
150
anatofuz
parents:
diff changeset
466 Archive.dump_header(f=result)
anatofuz
parents:
diff changeset
467 for match in archive.objects:
anatofuz
parents:
diff changeset
468 match.dump(f=result, flat=True)
anatofuz
parents:
diff changeset
469 # archive.dump(f=result, flat=True)
anatofuz
parents:
diff changeset
470
anatofuz
parents:
diff changeset
471
anatofuz
parents:
diff changeset
472 class VerifyDebugMapCommand:
anatofuz
parents:
diff changeset
473 name = "verify-debug-map-objects"
anatofuz
parents:
diff changeset
474
anatofuz
parents:
diff changeset
475 def create_options(self):
anatofuz
parents:
diff changeset
476 usage = "usage: %prog [options]"
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
477 description = """This command reports any .o files that are missing
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
478 or whose modification times don't match in the debug map of an executable."""
150
anatofuz
parents:
diff changeset
479
anatofuz
parents:
diff changeset
480 self.parser = optparse.OptionParser(
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
481 description=description, prog=self.name, usage=usage, add_help_option=False
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
482 )
150
anatofuz
parents:
diff changeset
483
anatofuz
parents:
diff changeset
484 self.parser.add_option(
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
485 "-e",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
486 "--errors",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
487 action="store_true",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
488 dest="errors",
150
anatofuz
parents:
diff changeset
489 default=False,
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
490 help="Only show errors",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
491 )
150
anatofuz
parents:
diff changeset
492
anatofuz
parents:
diff changeset
493 def get_short_help(self):
anatofuz
parents:
diff changeset
494 return "Verify debug map object files."
anatofuz
parents:
diff changeset
495
anatofuz
parents:
diff changeset
496 def get_long_help(self):
anatofuz
parents:
diff changeset
497 return self.help_string
anatofuz
parents:
diff changeset
498
anatofuz
parents:
diff changeset
499 def __init__(self, debugger, unused):
anatofuz
parents:
diff changeset
500 self.create_options()
anatofuz
parents:
diff changeset
501 self.help_string = self.parser.format_help()
anatofuz
parents:
diff changeset
502
anatofuz
parents:
diff changeset
503 def __call__(self, debugger, command, exe_ctx, result):
anatofuz
parents:
diff changeset
504 import lldb
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
505
150
anatofuz
parents:
diff changeset
506 # Use the Shell Lexer to properly parse up command options just like a
anatofuz
parents:
diff changeset
507 # shell would
anatofuz
parents:
diff changeset
508 command_args = shlex.split(command)
anatofuz
parents:
diff changeset
509
anatofuz
parents:
diff changeset
510 try:
anatofuz
parents:
diff changeset
511 (options, args) = self.parser.parse_args(command_args)
anatofuz
parents:
diff changeset
512 except:
anatofuz
parents:
diff changeset
513 result.SetError("option parsing failed")
anatofuz
parents:
diff changeset
514 return
anatofuz
parents:
diff changeset
515
anatofuz
parents:
diff changeset
516 # Always get program state from the SBExecutionContext passed in
anatofuz
parents:
diff changeset
517 target = exe_ctx.GetTarget()
anatofuz
parents:
diff changeset
518 if not target.IsValid():
anatofuz
parents:
diff changeset
519 result.SetError("invalid target")
anatofuz
parents:
diff changeset
520 return
anatofuz
parents:
diff changeset
521 archives = {}
anatofuz
parents:
diff changeset
522 for module_spec in args:
anatofuz
parents:
diff changeset
523 module = target.module[module_spec]
anatofuz
parents:
diff changeset
524 if not (module and module.IsValid()):
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
525 result.SetError(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
526 'error: invalid module specification: "%s". '
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
527 "Specify the full path, basename, or UUID of "
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
528 "a module " % (module_spec)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
529 )
150
anatofuz
parents:
diff changeset
530 return
anatofuz
parents:
diff changeset
531 num_symbols = module.GetNumSymbols()
anatofuz
parents:
diff changeset
532 num_errors = 0
anatofuz
parents:
diff changeset
533 for i in range(num_symbols):
anatofuz
parents:
diff changeset
534 symbol = module.GetSymbolAtIndex(i)
anatofuz
parents:
diff changeset
535 if symbol.GetType() != lldb.eSymbolTypeObjectFile:
anatofuz
parents:
diff changeset
536 continue
anatofuz
parents:
diff changeset
537 path = symbol.GetName()
anatofuz
parents:
diff changeset
538 if not path:
anatofuz
parents:
diff changeset
539 continue
anatofuz
parents:
diff changeset
540 # Extract the value of the symbol by dumping the
anatofuz
parents:
diff changeset
541 # symbol. The value is the mod time.
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
542 dmap_mtime = int(str(symbol).split("value = ")[1].split(",")[0], 16)
150
anatofuz
parents:
diff changeset
543 if not options.errors:
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
544 print("%s" % (path), file=result)
150
anatofuz
parents:
diff changeset
545 if os.path.exists(path):
anatofuz
parents:
diff changeset
546 actual_mtime = int(os.stat(path).st_mtime)
anatofuz
parents:
diff changeset
547 if dmap_mtime != actual_mtime:
anatofuz
parents:
diff changeset
548 num_errors += 1
anatofuz
parents:
diff changeset
549 if options.errors:
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
550 print("%s" % (path), end=" ", file=result)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
551 print_mtime_error(result, dmap_mtime, actual_mtime)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
552 elif path[-1] == ")":
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
553 (archive_path, object_name) = path[0:-1].split("(")
150
anatofuz
parents:
diff changeset
554 if not archive_path and not object_name:
anatofuz
parents:
diff changeset
555 num_errors += 1
anatofuz
parents:
diff changeset
556 if options.errors:
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
557 print("%s" % (path), end=" ", file=result)
150
anatofuz
parents:
diff changeset
558 print_file_missing_error(path)
anatofuz
parents:
diff changeset
559 continue
anatofuz
parents:
diff changeset
560 if not os.path.exists(archive_path):
anatofuz
parents:
diff changeset
561 num_errors += 1
anatofuz
parents:
diff changeset
562 if options.errors:
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
563 print("%s" % (path), end=" ", file=result)
150
anatofuz
parents:
diff changeset
564 print_file_missing_error(archive_path)
anatofuz
parents:
diff changeset
565 continue
anatofuz
parents:
diff changeset
566 if archive_path in archives:
anatofuz
parents:
diff changeset
567 archive = archives[archive_path]
anatofuz
parents:
diff changeset
568 else:
anatofuz
parents:
diff changeset
569 archive = Archive(archive_path)
anatofuz
parents:
diff changeset
570 archives[archive_path] = archive
anatofuz
parents:
diff changeset
571 matches = archive.find(object_name, dmap_mtime)
anatofuz
parents:
diff changeset
572 num_matches = len(matches)
anatofuz
parents:
diff changeset
573 if num_matches == 1:
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
574 print("1 match", file=result)
150
anatofuz
parents:
diff changeset
575 obj = matches[0]
anatofuz
parents:
diff changeset
576 if obj.date != dmap_mtime:
anatofuz
parents:
diff changeset
577 num_errors += 1
anatofuz
parents:
diff changeset
578 if options.errors:
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
579 print("%s" % (path), end=" ", file=result)
150
anatofuz
parents:
diff changeset
580 print_mtime_error(result, dmap_mtime, obj.date)
anatofuz
parents:
diff changeset
581 elif num_matches == 0:
anatofuz
parents:
diff changeset
582 num_errors += 1
anatofuz
parents:
diff changeset
583 if options.errors:
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
584 print("%s" % (path), end=" ", file=result)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
585 print_archive_object_error(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
586 result, object_name, dmap_mtime, archive
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
587 )
150
anatofuz
parents:
diff changeset
588 elif num_matches > 1:
anatofuz
parents:
diff changeset
589 num_errors += 1
anatofuz
parents:
diff changeset
590 if options.errors:
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
591 print("%s" % (path), end=" ", file=result)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
592 print_multiple_object_matches(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
593 result, object_name, dmap_mtime, matches
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
594 )
150
anatofuz
parents:
diff changeset
595 if num_errors > 0:
anatofuz
parents:
diff changeset
596 print("%u errors found" % (num_errors), file=result)
anatofuz
parents:
diff changeset
597 else:
anatofuz
parents:
diff changeset
598 print("No errors detected in debug map", file=result)
anatofuz
parents:
diff changeset
599
anatofuz
parents:
diff changeset
600
anatofuz
parents:
diff changeset
601 def __lldb_init_module(debugger, dict):
anatofuz
parents:
diff changeset
602 # This initializer is being run from LLDB in the embedded command
anatofuz
parents:
diff changeset
603 # interpreter.
anatofuz
parents:
diff changeset
604 # Add any commands contained in this module to LLDB
anatofuz
parents:
diff changeset
605 debugger.HandleCommand(
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
606 "command script add -o -c %s.VerifyDebugMapCommand %s"
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
607 % (__name__, VerifyDebugMapCommand.name)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
608 )
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
609 print(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
610 'The "%s" command has been installed, type "help %s" for detailed '
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
611 "help." % (VerifyDebugMapCommand.name, VerifyDebugMapCommand.name)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
612 )