Skip to content

Commit 42faef4

Browse files
authored
Merge pull request #6741 from apple/jdevlieghere/cherrypick-objectfile-json
Cherrypick ObjectFileJSON and SymbolFileJSON commits
2 parents b4a7b24 + 71b31d3 commit 42faef4

File tree

20 files changed

+383
-93
lines changed

20 files changed

+383
-93
lines changed

lldb/examples/python/crashlog.py

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ class Thread:
8080
def __init__(self, index, app_specific_backtrace):
8181
self.index = index
8282
self.id = index
83+
self.images = list()
8384
self.frames = list()
8485
self.idents = list()
8586
self.registers = dict()
@@ -456,6 +457,11 @@ def parse_json(buffer):
456457
except:
457458
return None
458459

460+
def __init__(self, debugger, path, verbose):
461+
super().__init__(debugger, path, verbose)
462+
# List of DarwinImages sorted by their index.
463+
self.images = list()
464+
459465
def parse(self):
460466
try:
461467
self.parse_process_info(self.data)
@@ -506,19 +512,19 @@ def parse_crash_reason(self, json_exception):
506512
exception_extra)
507513

508514
def parse_images(self, json_images):
509-
idx = 0
510515
for json_image in json_images:
511516
img_uuid = uuid.UUID(json_image['uuid'])
512517
low = int(json_image['base'])
513-
high = int(0)
518+
high = low + int(
519+
json_image['size']) if 'size' in json_image else low
514520
name = json_image['name'] if 'name' in json_image else ''
515521
path = json_image['path'] if 'path' in json_image else ''
516522
version = ''
517523
darwin_image = self.crashlog.DarwinImage(low, high, name, version,
518524
img_uuid, path,
519525
self.verbose)
526+
self.images.append(darwin_image)
520527
self.crashlog.images.append(darwin_image)
521-
idx += 1
522528

523529
def parse_main_image(self, json_data):
524530
if 'procName' in json_data:
@@ -538,6 +544,17 @@ def parse_frames(self, thread, json_frames):
538544
frame_offset = int(json_frame['imageOffset'])
539545
image_addr = self.get_used_image(image_id)['base']
540546
pc = image_addr + frame_offset
547+
548+
if 'symbol' in json_frame:
549+
symbol = json_frame['symbol']
550+
location = int(json_frame['symbolLocation'])
551+
image = self.images[image_id]
552+
image.symbols[symbol] = {
553+
"name": symbol,
554+
"type": "code",
555+
"address": frame_offset - location
556+
}
557+
541558
thread.frames.append(self.crashlog.Frame(idx, pc, frame_offset))
542559

543560
# on arm64 systems, if it jump through a null function pointer,
@@ -1014,40 +1031,25 @@ def SymbolicateCrashLog(crash_log, options):
10141031
target = crash_log.create_target()
10151032
if not target:
10161033
return
1017-
exe_module = target.GetModuleAtIndex(0)
1018-
images_to_load = list()
1019-
loaded_images = list()
1034+
1035+
10201036
if options.load_all_images:
1021-
# --load-all option was specified, load everything up
10221037
for image in crash_log.images:
1023-
images_to_load.append(image)
1024-
else:
1025-
# Only load the images found in stack frames for the crashed threads
1026-
if options.crashed_only:
1027-
for thread in crash_log.threads:
1028-
if thread.did_crash():
1029-
for ident in thread.idents:
1030-
images = crash_log.find_images_with_identifier(ident)
1031-
if images:
1032-
for image in images:
1033-
images_to_load.append(image)
1034-
else:
1035-
print('error: can\'t find image for identifier "%s"' % ident)
1036-
else:
1037-
for ident in crash_log.idents:
1038-
images = crash_log.find_images_with_identifier(ident)
1039-
if images:
1040-
for image in images:
1041-
images_to_load.append(image)
1042-
else:
1043-
print('error: can\'t find image for identifier "%s"' % ident)
1038+
image.resolve = True
1039+
elif options.crashed_only:
1040+
for thread in crash_log.threads:
1041+
if thread.did_crash():
1042+
for ident in thread.idents:
1043+
for image in self.crashlog.find_images_with_identifier(ident):
1044+
image.resolve = True
10441045

10451046
futures = []
1047+
loaded_images = []
10461048
with concurrent.futures.ThreadPoolExecutor() as executor:
10471049
def add_module(image, target):
10481050
return image, image.add_module(target)
10491051

1050-
for image in images_to_load:
1052+
for image in crash_log.images:
10511053
futures.append(executor.submit(add_module, image=image, target=target))
10521054

10531055
for future in concurrent.futures.as_completed(futures):
@@ -1110,12 +1112,17 @@ def load_crashlog_in_scripted_process(debugger, crash_log_file, options, result)
11101112
launch_info.SetProcessPluginName("ScriptedProcess")
11111113
launch_info.SetScriptedProcessClassName("crashlog_scripted_process.CrashLogScriptedProcess")
11121114
launch_info.SetScriptedProcessDictionary(structured_data)
1115+
launch_info.SetLaunchFlags(lldb.eLaunchFlagStopAtEntry)
1116+
11131117
error = lldb.SBError()
11141118
process = target.Launch(launch_info, error)
11151119

11161120
if not process or error.Fail():
11171121
raise InteractiveCrashLogException("couldn't launch Scripted Process", error)
11181122

1123+
process.GetScriptedImplementation().set_crashlog(crashlog)
1124+
process.Continue()
1125+
11191126
if not options.skip_status:
11201127
@contextlib.contextmanager
11211128
def synchronous(debugger):

lldb/examples/python/scripted_process/crashlog_scripted_process.py

Lines changed: 33 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,42 +9,41 @@
99
from lldb.macosx.crashlog import CrashLog,CrashLogParser
1010

1111
class CrashLogScriptedProcess(ScriptedProcess):
12-
def parse_crashlog(self):
13-
crashlog_parser = CrashLogParser.create(self.dbg, self.crashlog_path, False)
14-
crash_log = crashlog_parser.parse()
15-
16-
self.pid = crash_log.process_id
17-
self.addr_mask = crash_log.addr_mask
18-
self.crashed_thread_idx = crash_log.crashed_thread_idx
12+
def set_crashlog(self, crashlog):
13+
self.crashlog = crashlog
14+
self.pid = self.crashlog.process_id
15+
self.addr_mask = self.crashlog.addr_mask
16+
self.crashed_thread_idx = self.crashlog.crashed_thread_idx
1917
self.loaded_images = []
20-
self.exception = crash_log.exception
18+
self.exception = self.crashlog.exception
2119
self.app_specific_thread = None
22-
if hasattr(crash_log, 'asi'):
23-
self.metadata['asi'] = crash_log.asi
24-
if hasattr(crash_log, 'asb'):
25-
self.extended_thread_info = crash_log.asb
26-
27-
def load_images(self, images):
28-
#TODO: Add to self.loaded_images and load images in lldb
29-
if images:
30-
for image in images:
31-
if image not in self.loaded_images:
32-
if image.uuid == uuid.UUID(int=0):
33-
continue
34-
err = image.add_module(self.target)
35-
if err:
36-
# Append to SBCommandReturnObject
37-
print(err)
38-
else:
39-
self.loaded_images.append(image)
40-
41-
for thread in crash_log.threads:
42-
if self.load_all_images:
43-
load_images(self, crash_log.images)
44-
elif thread.did_crash():
45-
for ident in thread.idents:
46-
load_images(self, crash_log.find_images_with_identifier(ident))
47-
20+
if hasattr(self.crashlog, 'asi'):
21+
self.metadata['asi'] = self.crashlog.asi
22+
if hasattr(self.crashlog, 'asb'):
23+
self.extended_thread_info = self.crashlog.asb
24+
25+
if self.load_all_images:
26+
for image in self.crashlog.images:
27+
image.resolve = True
28+
else:
29+
for thread in self.crashlog.threads:
30+
if thread.did_crash():
31+
for ident in thread.idents:
32+
for image in self.crashlog.find_images_with_identifier(ident):
33+
image.resolve = True
34+
35+
for image in self.crashlog.images:
36+
if image not in self.loaded_images:
37+
if image.uuid == uuid.UUID(int=0):
38+
continue
39+
err = image.add_module(self.target)
40+
if err:
41+
# Append to SBCommandReturnObject
42+
print(err)
43+
else:
44+
self.loaded_images.append(image)
45+
46+
for thread in self.crashlog.threads:
4847
if hasattr(thread, 'app_specific_backtrace') and thread.app_specific_backtrace:
4948
# We don't want to include the Application Specific Backtrace
5049
# Thread into the Scripted Process' Thread list.
@@ -92,7 +91,6 @@ def __init__(self, exe_ctx: lldb.SBExecutionContext, args : lldb.SBStructuredDat
9291
self.crashed_thread_idx = 0
9392
self.exception = None
9493
self.extended_thread_info = None
95-
self.parse_crashlog()
9694

9795
def read_memory_at_address(self, addr: int, size: int, error: lldb.SBError) -> lldb.SBData:
9896
# NOTE: CrashLogs don't contain any memory.
@@ -103,9 +101,6 @@ def get_loaded_images(self):
103101
# from it.
104102
return self.loaded_images
105103

106-
def get_process_id(self) -> int:
107-
return self.pid
108-
109104
def should_stop(self) -> bool:
110105
return True
111106

lldb/examples/python/scripted_process/scripted_process.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ def __init__(self, exe_ctx, args):
4747
self.loaded_images = []
4848
self.metadata = {}
4949
self.capabilities = {}
50+
self.pid = 42
5051

5152
def get_capabilities(self):
5253
""" Get a dictionary containing the process capabilities.
@@ -138,7 +139,7 @@ def get_process_id(self):
138139
Returns:
139140
int: The scripted process identifier.
140141
"""
141-
return 0
142+
return self.pid
142143

143144
def launch(self):
144145
""" Simulate the scripted process launch.

lldb/examples/python/symbolication.py

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
import sys
3636
import time
3737
import uuid
38+
import json
39+
import tempfile
3840

3941

4042
class Address:
@@ -230,6 +232,7 @@ class Image:
230232
def __init__(self, path, uuid=None):
231233
self.path = path
232234
self.resolved_path = None
235+
self.resolve = False
233236
self.resolved = False
234237
self.unavailable = False
235238
self.uuid = uuid
@@ -240,6 +243,7 @@ def __init__(self, path, uuid=None):
240243
self.module = None
241244
self.symfile = None
242245
self.slide = None
246+
self.symbols = dict()
243247

244248
@classmethod
245249
def InitWithSBTargetAndSBModule(cls, target, module):
@@ -372,14 +376,32 @@ def add_module(self, target):
372376
uuid_str = self.get_normalized_uuid_string()
373377
if uuid_str:
374378
self.module = target.AddModule(None, None, uuid_str)
375-
if not self.module:
379+
if not self.module and self.resolve:
376380
self.locate_module_and_debug_symbols()
377-
if self.unavailable:
378-
return None
379-
resolved_path = self.get_resolved_path()
380-
self.module = target.AddModule(
381-
resolved_path, None, uuid_str, self.symfile)
382-
if not self.module:
381+
if not self.unavailable:
382+
resolved_path = self.get_resolved_path()
383+
self.module = target.AddModule(
384+
resolved_path, None, uuid_str, self.symfile)
385+
if not self.module and self.section_infos:
386+
name = os.path.basename(self.path)
387+
with tempfile.NamedTemporaryFile(suffix='.' + name) as tf:
388+
data = {
389+
'triple': target.triple,
390+
'uuid': uuid_str,
391+
'type': 'sharedlibrary',
392+
'sections': list(),
393+
'symbols': list()
394+
}
395+
for section in self.section_infos:
396+
data['sections'].append({
397+
'name' : section.name,
398+
'size': section.end_addr - section.start_addr
399+
})
400+
data['symbols'] = list(self.symbols.values())
401+
with open(tf.name, 'w') as f:
402+
f.write(json.dumps(data, indent=4))
403+
self.module = target.AddModule(tf.name, None, uuid_str)
404+
if not self.module and not self.unavailable:
383405
return 'error: unable to get module for (%s) "%s"' % (
384406
self.arch, self.get_resolved_path())
385407
if self.has_section_load_info():

lldb/include/lldb/Core/Section.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "lldb/lldb-enumerations.h"
1818
#include "lldb/lldb-forward.h"
1919
#include "lldb/lldb-types.h"
20+
#include "llvm/Support/JSON.h"
2021

2122
#include <memory>
2223
#include <vector>
@@ -99,6 +100,13 @@ class SectionList {
99100
collection m_sections;
100101
};
101102

103+
struct JSONSection {
104+
std::string name;
105+
llvm::Optional<lldb::SectionType> type;
106+
llvm::Optional<uint64_t> address;
107+
llvm::Optional<uint64_t> size;
108+
};
109+
102110
class Section : public std::enable_shared_from_this<Section>,
103111
public ModuleChild,
104112
public UserID,
@@ -294,4 +302,16 @@ class Section : public std::enable_shared_from_this<Section>,
294302

295303
} // namespace lldb_private
296304

305+
namespace llvm {
306+
namespace json {
307+
308+
bool fromJSON(const llvm::json::Value &value,
309+
lldb_private::JSONSection &section, llvm::json::Path path);
310+
311+
bool fromJSON(const llvm::json::Value &value, lldb::SectionType &type,
312+
llvm::json::Path path);
313+
314+
} // namespace json
315+
} // namespace llvm
316+
297317
#endif // LLDB_CORE_SECTION_H

lldb/include/lldb/Symbol/ObjectFile.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,11 @@ template <> struct format_provider<lldb_private::ObjectFile::Strata> {
799799
static void format(const lldb_private::ObjectFile::Strata &strata,
800800
raw_ostream &OS, StringRef Style);
801801
};
802+
803+
namespace json {
804+
bool fromJSON(const llvm::json::Value &value, lldb_private::ObjectFile::Type &,
805+
llvm::json::Path path);
806+
} // namespace json
802807
} // namespace llvm
803808

804809
#endif // LLDB_SYMBOL_OBJECTFILE_H

lldb/source/Core/Section.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,3 +691,36 @@ uint64_t SectionList::GetDebugInfoSize() const {
691691
}
692692
return debug_info_size;
693693
}
694+
695+
namespace llvm {
696+
namespace json {
697+
698+
bool fromJSON(const llvm::json::Value &value,
699+
lldb_private::JSONSection &section, llvm::json::Path path) {
700+
llvm::json::ObjectMapper o(value, path);
701+
return o && o.map("name", section.name) && o.map("type", section.type) &&
702+
o.map("size", section.address) && o.map("size", section.size);
703+
}
704+
705+
bool fromJSON(const llvm::json::Value &value, lldb::SectionType &type,
706+
llvm::json::Path path) {
707+
if (auto str = value.getAsString()) {
708+
type = llvm::StringSwitch<lldb::SectionType>(*str)
709+
.Case("code", eSectionTypeCode)
710+
.Case("container", eSectionTypeContainer)
711+
.Case("data", eSectionTypeData)
712+
.Case("debug", eSectionTypeDebug)
713+
.Default(eSectionTypeInvalid);
714+
715+
if (type == eSectionTypeInvalid) {
716+
path.report("invalid section type");
717+
return false;
718+
}
719+
720+
return true;
721+
}
722+
path.report("expected string");
723+
return false;
724+
}
725+
} // namespace json
726+
} // namespace llvm

0 commit comments

Comments
 (0)