Skip to content

Commit 2350f42

Browse files
authored
Merge pull request #6826 from apple/eng/r109116249-debugserver-flag-to-only-report-binary-image-load-addrs
Add a new report_load_commands option to jGetLoadedDynamicLibrariesInfos
2 parents 0c72892 + 2d38a6b commit 2350f42

File tree

9 files changed

+65
-183
lines changed

9 files changed

+65
-183
lines changed

lldb/docs/lldb-gdb-remote.txt

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1961,19 +1961,16 @@ for this region.
19611961
// This packet asks the remote debug stub to send the details about libraries
19621962
// being added/removed from the process as a performance optimization.
19631963
//
1964-
// There are three ways this packet can be used. All three return a dictionary of
1964+
// There are two ways this packet can be used. Both return a dictionary of
19651965
// binary images formatted the same way.
19661966
//
1967-
// On OS X 10.11, iOS 9, tvOS 9, watchOS 2 and earlier, the packet is used like
1968-
// jGetLoadedDynamicLibrariesInfos:{"image_count":1,"image_list_address":140734800075128}
1969-
// where the image_list_address is an array of {void* load_addr, void* mod_date, void* pathname}
1970-
// in the inferior process memory (and image_count is the number of elements in this array).
1971-
// lldb is using information from the dyld_all_image_infos structure to make these requests to
1972-
// debugserver. This use is not supported on macOS 10.12, iOS 10, tvOS 10, watchOS 3 or newer.
1973-
//
1974-
// On macOS 10.12, iOS 10, tvOS 10, watchOS 3 and newer, there are two calls. One requests information
1975-
// on all shared libraries:
1967+
// One requests information on all shared libraries:
19761968
// jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true}
1969+
// with an optional `"report_load_commands":false` which can be added, asking
1970+
// that only the dyld SPI information (load addresses, filenames) be returned.
1971+
// The default behavior is that debugserver scans the mach-o header and load
1972+
// commands of each binary, and returns it in the JSON reply.
1973+
//
19771974
// And the second requests information about a list of shared libraries, given their load addresses:
19781975
// jGetLoadedDynamicLibrariesInfos:{"solib_addresses":[8382824135,3258302053,830202858503]}
19791976
//

lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,6 @@ bool DynamicLoaderDarwin::JSONImageInformationIntoImageInfo(
372372
// clang-format off
373373
if (!image->HasKey("load_address") ||
374374
!image->HasKey("pathname") ||
375-
!image->HasKey("mod_date") ||
376375
!image->HasKey("mach_header") ||
377376
image->GetValueForKey("mach_header")->GetAsDictionary() == nullptr ||
378377
!image->HasKey("segments") ||
@@ -383,8 +382,6 @@ bool DynamicLoaderDarwin::JSONImageInformationIntoImageInfo(
383382
// clang-format on
384383
image_infos[i].address =
385384
image->GetValueForKey("load_address")->GetAsInteger()->GetValue();
386-
image_infos[i].mod_date =
387-
image->GetValueForKey("mod_date")->GetAsInteger()->GetValue();
388385
image_infos[i].file_spec.SetFile(
389386
image->GetValueForKey("pathname")->GetAsString()->GetValue(),
390387
FileSpec::Style::native);
@@ -811,11 +808,11 @@ void DynamicLoaderDarwin::ImageInfo::PutToLog(Log *log) const {
811808
if (!log)
812809
return;
813810
if (address == LLDB_INVALID_ADDRESS) {
814-
LLDB_LOG(log, "modtime={0:x+8} uuid={1} path='{2}' (UNLOADED)", mod_date,
815-
uuid.GetAsString(), file_spec.GetPath());
811+
LLDB_LOG(log, "uuid={1} path='{2}' (UNLOADED)", uuid.GetAsString(),
812+
file_spec.GetPath());
816813
} else {
817-
LLDB_LOG(log, "address={0:x+16} modtime={1:x+8} uuid={2} path='{3}'",
818-
address, mod_date, uuid.GetAsString(), file_spec.GetPath());
814+
LLDB_LOG(log, "address={0:x+16} uuid={2} path='{3}'", address,
815+
uuid.GetAsString(), file_spec.GetPath());
819816
for (uint32_t i = 0; i < segments.size(); ++i)
820817
segments[i].PutToLog(log, slide);
821818
}

lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,6 @@ class DynamicLoaderDarwin : public lldb_private::DynamicLoader {
100100
/// The amount to slide all segments by if there is a global
101101
/// slide.
102102
lldb::addr_t slide = 0;
103-
/// Modification date for this dylib.
104-
lldb::addr_t mod_date = 0;
105103
/// Resolved path for this dylib.
106104
lldb_private::FileSpec file_spec;
107105
/// UUID for this dylib if it has one, else all zeros.
@@ -128,7 +126,6 @@ class DynamicLoaderDarwin : public lldb_private::DynamicLoader {
128126
if (!load_cmd_data_only) {
129127
address = LLDB_INVALID_ADDRESS;
130128
slide = 0;
131-
mod_date = 0;
132129
file_spec.Clear();
133130
::memset(&header, 0, sizeof(header));
134131
}
@@ -142,8 +139,7 @@ class DynamicLoaderDarwin : public lldb_private::DynamicLoader {
142139

143140
bool operator==(const ImageInfo &rhs) const {
144141
return address == rhs.address && slide == rhs.slide &&
145-
mod_date == rhs.mod_date && file_spec == rhs.file_spec &&
146-
uuid == rhs.uuid &&
142+
file_spec == rhs.file_spec && uuid == rhs.uuid &&
147143
memcmp(&header, &rhs.header, sizeof(header)) == 0 &&
148144
segments == rhs.segments && os_type == rhs.os_type &&
149145
os_env == rhs.os_env;

lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -693,7 +693,7 @@ bool DynamicLoaderMacOSXDYLD::ReadImageInfos(
693693
i++) {
694694
image_infos[i].address = info_data_ref.GetAddress(&info_data_offset);
695695
lldb::addr_t path_addr = info_data_ref.GetAddress(&info_data_offset);
696-
image_infos[i].mod_date = info_data_ref.GetAddress(&info_data_offset);
696+
info_data_ref.GetAddress(&info_data_offset); // mod_date, unused */
697697

698698
char raw_path[PATH_MAX];
699699
m_process->ReadCStringFromMemory(path_addr, raw_path, sizeof(raw_path),

lldb/tools/debugserver/source/DNB.cpp

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,20 +1023,11 @@ DNBGetTSDAddressForThread(nub_process_t pid, nub_thread_t tid,
10231023
return INVALID_NUB_ADDRESS;
10241024
}
10251025

1026-
JSONGenerator::ObjectSP DNBGetLoadedDynamicLibrariesInfos(
1027-
nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count) {
1028-
MachProcessSP procSP;
1029-
if (GetProcessSP(pid, procSP)) {
1030-
return procSP->GetLoadedDynamicLibrariesInfos(pid, image_list_address,
1031-
image_count);
1032-
}
1033-
return JSONGenerator::ObjectSP();
1034-
}
1035-
1036-
JSONGenerator::ObjectSP DNBGetAllLoadedLibrariesInfos(nub_process_t pid) {
1026+
JSONGenerator::ObjectSP
1027+
DNBGetAllLoadedLibrariesInfos(nub_process_t pid, bool report_load_commands) {
10371028
MachProcessSP procSP;
10381029
if (GetProcessSP(pid, procSP)) {
1039-
return procSP->GetAllLoadedLibrariesInfos(pid);
1030+
return procSP->GetAllLoadedLibrariesInfos(pid, report_load_commands);
10401031
}
10411032
return JSONGenerator::ObjectSP();
10421033
}

lldb/tools/debugserver/source/DNB.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,8 @@ DNBGetTSDAddressForThread(nub_process_t pid, nub_thread_t tid,
210210
uint64_t plo_pthread_tsd_base_address_offset,
211211
uint64_t plo_pthread_tsd_base_offset,
212212
uint64_t plo_pthread_tsd_entry_size);
213-
JSONGenerator::ObjectSP DNBGetLoadedDynamicLibrariesInfos(
214-
nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count);
215-
JSONGenerator::ObjectSP DNBGetAllLoadedLibrariesInfos(nub_process_t pid);
213+
JSONGenerator::ObjectSP
214+
DNBGetAllLoadedLibrariesInfos(nub_process_t pid, bool report_load_commands);
216215
JSONGenerator::ObjectSP
217216
DNBGetLibrariesInfoForAddresses(nub_process_t pid,
218217
std::vector<uint64_t> &macho_addresses);

lldb/tools/debugserver/source/MacOSX/MachProcess.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,11 @@ class MachProcess {
7272
struct binary_image_information {
7373
std::string filename;
7474
uint64_t load_address;
75-
uint64_t mod_date; // may not be available - 0 if so
7675
struct mach_o_information macho_info;
7776
bool is_valid_mach_header;
7877

7978
binary_image_information()
80-
: filename(), load_address(INVALID_NUB_ADDRESS), mod_date(0),
79+
: filename(), load_address(INVALID_NUB_ADDRESS),
8180
is_valid_mach_header(false) {}
8281
};
8382

@@ -259,7 +258,8 @@ class MachProcess {
259258
int wordsize,
260259
struct mach_o_information &inf);
261260
JSONGenerator::ObjectSP FormatDynamicLibrariesIntoJSON(
262-
const std::vector<struct binary_image_information> &image_infos);
261+
const std::vector<struct binary_image_information> &image_infos,
262+
bool report_load_commands);
263263
uint32_t GetPlatform();
264264
/// Get the runtime platform from DYLD via SPI.
265265
uint32_t GetProcessPlatformViaDYLDSPI();
@@ -271,12 +271,12 @@ class MachProcess {
271271
/// command details.
272272
void GetAllLoadedBinariesViaDYLDSPI(
273273
std::vector<struct binary_image_information> &image_infos);
274-
JSONGenerator::ObjectSP GetLoadedDynamicLibrariesInfos(
275-
nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count);
276274
JSONGenerator::ObjectSP
277275
GetLibrariesInfoForAddresses(nub_process_t pid,
278276
std::vector<uint64_t> &macho_addresses);
279-
JSONGenerator::ObjectSP GetAllLoadedLibrariesInfos(nub_process_t pid);
277+
JSONGenerator::ObjectSP
278+
GetAllLoadedLibrariesInfos(nub_process_t pid,
279+
bool fetch_report_load_commands);
280280
JSONGenerator::ObjectSP GetSharedCacheInfo(nub_process_t pid);
281281

282282
nub_size_t GetNumThreads() const;

lldb/tools/debugserver/source/MacOSX/MachProcess.mm

Lines changed: 29 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -912,22 +912,34 @@ static bool mach_header_validity_test(uint32_t magic, uint32_t cputype) {
912912
// create a JSONGenerator object
913913
// with all the details we want to send to lldb.
914914
JSONGenerator::ObjectSP MachProcess::FormatDynamicLibrariesIntoJSON(
915-
const std::vector<struct binary_image_information> &image_infos) {
915+
const std::vector<struct binary_image_information> &image_infos,
916+
bool report_load_commands) {
916917

917918
JSONGenerator::ArraySP image_infos_array_sp(new JSONGenerator::Array());
918919

919920
const size_t image_count = image_infos.size();
920921

921922
for (size_t i = 0; i < image_count; i++) {
922-
if (!image_infos[i].is_valid_mach_header)
923+
// If we should report the Mach-O header and load commands,
924+
// and those were unreadable, don't report anything about this
925+
// binary.
926+
if (report_load_commands && !image_infos[i].is_valid_mach_header)
923927
continue;
924928
JSONGenerator::DictionarySP image_info_dict_sp(
925929
new JSONGenerator::Dictionary());
926930
image_info_dict_sp->AddIntegerItem("load_address",
927931
image_infos[i].load_address);
928-
image_info_dict_sp->AddIntegerItem("mod_date", image_infos[i].mod_date);
932+
// TODO: lldb currently rejects a response without this, but it
933+
// is always zero from dyld. It can be removed once we've had time
934+
// for lldb's that require it to be present are obsolete.
935+
image_info_dict_sp->AddIntegerItem("mod_date", 0);
929936
image_info_dict_sp->AddStringItem("pathname", image_infos[i].filename);
930937

938+
if (!report_load_commands) {
939+
image_infos_array_sp->AddItem(image_info_dict_sp);
940+
continue;
941+
}
942+
931943
uuid_string_t uuidstr;
932944
uuid_unparse_upper(image_infos[i].macho_info.uuid, uuidstr);
933945
image_info_dict_sp->AddStringItem("uuid", uuidstr);
@@ -1000,109 +1012,6 @@ static bool mach_header_validity_test(uint32_t magic, uint32_t cputype) {
10001012
return reply_sp;
10011013
}
10021014

1003-
// Get the shared library information using the old (pre-macOS 10.12, pre-iOS
1004-
// 10, pre-tvOS 10, pre-watchOS 3)
1005-
// code path. We'll be given the address of an array of structures in the form
1006-
// {void* load_addr, void* mod_date, void* pathname}
1007-
//
1008-
// In macOS 10.12 etc and newer, we'll use SPI calls into dyld to gather this
1009-
// information.
1010-
JSONGenerator::ObjectSP MachProcess::GetLoadedDynamicLibrariesInfos(
1011-
nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count) {
1012-
1013-
JSONGenerator::ObjectSP empty_reply_sp(new JSONGenerator::Dictionary());
1014-
int pointer_size = GetInferiorAddrSize(pid);
1015-
1016-
std::vector<struct binary_image_information> image_infos;
1017-
size_t image_infos_size = image_count * 3 * pointer_size;
1018-
1019-
uint8_t *image_info_buf = (uint8_t *)malloc(image_infos_size);
1020-
if (image_info_buf == NULL) {
1021-
return empty_reply_sp;
1022-
}
1023-
if (ReadMemory(image_list_address, image_infos_size, image_info_buf) !=
1024-
image_infos_size) {
1025-
return empty_reply_sp;
1026-
}
1027-
1028-
/// First the image_infos array with (load addr, pathname, mod date)
1029-
/// tuples
1030-
1031-
for (size_t i = 0; i < image_count; i++) {
1032-
struct binary_image_information info;
1033-
nub_addr_t pathname_address;
1034-
if (pointer_size == 4) {
1035-
uint32_t load_address_32;
1036-
uint32_t pathname_address_32;
1037-
uint32_t mod_date_32;
1038-
::memcpy(&load_address_32, image_info_buf + (i * 3 * pointer_size), 4);
1039-
::memcpy(&pathname_address_32,
1040-
image_info_buf + (i * 3 * pointer_size) + pointer_size, 4);
1041-
::memcpy(&mod_date_32,
1042-
image_info_buf + (i * 3 * pointer_size) + pointer_size +
1043-
pointer_size,
1044-
4);
1045-
info.load_address = load_address_32;
1046-
info.mod_date = mod_date_32;
1047-
pathname_address = pathname_address_32;
1048-
} else {
1049-
uint64_t load_address_64;
1050-
uint64_t pathname_address_64;
1051-
uint64_t mod_date_64;
1052-
::memcpy(&load_address_64, image_info_buf + (i * 3 * pointer_size), 8);
1053-
::memcpy(&pathname_address_64,
1054-
image_info_buf + (i * 3 * pointer_size) + pointer_size, 8);
1055-
::memcpy(&mod_date_64,
1056-
image_info_buf + (i * 3 * pointer_size) + pointer_size +
1057-
pointer_size,
1058-
8);
1059-
info.load_address = load_address_64;
1060-
info.mod_date = mod_date_64;
1061-
pathname_address = pathname_address_64;
1062-
}
1063-
char strbuf[17];
1064-
info.filename = "";
1065-
uint64_t pathname_ptr = pathname_address;
1066-
bool still_reading = true;
1067-
while (still_reading && ReadMemory(pathname_ptr, sizeof(strbuf) - 1,
1068-
strbuf) == sizeof(strbuf) - 1) {
1069-
strbuf[sizeof(strbuf) - 1] = '\0';
1070-
info.filename += strbuf;
1071-
pathname_ptr += sizeof(strbuf) - 1;
1072-
// Stop if we found nul byte indicating the end of the string
1073-
for (size_t i = 0; i < sizeof(strbuf) - 1; i++) {
1074-
if (strbuf[i] == '\0') {
1075-
still_reading = false;
1076-
break;
1077-
}
1078-
}
1079-
}
1080-
uuid_clear(info.macho_info.uuid);
1081-
image_infos.push_back(info);
1082-
}
1083-
if (image_infos.size() == 0) {
1084-
return empty_reply_sp;
1085-
}
1086-
1087-
free(image_info_buf);
1088-
1089-
/// Second, read the mach header / load commands for all the dylibs
1090-
1091-
for (size_t i = 0; i < image_count; i++) {
1092-
// The SPI to provide platform is not available on older systems.
1093-
uint32_t platform = 0;
1094-
if (GetMachOInformationFromMemory(platform, image_infos[i].load_address,
1095-
pointer_size,
1096-
image_infos[i].macho_info)) {
1097-
image_infos[i].is_valid_mach_header = true;
1098-
}
1099-
}
1100-
1101-
/// Third, format all of the above in the JSONGenerator object.
1102-
1103-
return FormatDynamicLibrariesIntoJSON(image_infos);
1104-
}
1105-
11061015
/// From dyld SPI header dyld_process_info.h
11071016
typedef void *dyld_process_info;
11081017
struct dyld_process_cache_info {
@@ -1162,21 +1071,24 @@ static bool mach_header_validity_test(uint32_t magic, uint32_t cputype) {
11621071
// in
11631072
// macOS 10.12, iOS 10, tvOS 10, watchOS 3 and newer.
11641073
JSONGenerator::ObjectSP
1165-
MachProcess::GetAllLoadedLibrariesInfos(nub_process_t pid) {
1074+
MachProcess::GetAllLoadedLibrariesInfos(nub_process_t pid,
1075+
bool report_load_commands) {
11661076

11671077
int pointer_size = GetInferiorAddrSize(pid);
11681078
std::vector<struct binary_image_information> image_infos;
11691079
GetAllLoadedBinariesViaDYLDSPI(image_infos);
1170-
uint32_t platform = GetPlatform();
1171-
const size_t image_count = image_infos.size();
1172-
for (size_t i = 0; i < image_count; i++) {
1173-
if (GetMachOInformationFromMemory(platform, image_infos[i].load_address,
1174-
pointer_size,
1175-
image_infos[i].macho_info)) {
1176-
image_infos[i].is_valid_mach_header = true;
1080+
if (report_load_commands) {
1081+
uint32_t platform = GetPlatform();
1082+
const size_t image_count = image_infos.size();
1083+
for (size_t i = 0; i < image_count; i++) {
1084+
if (GetMachOInformationFromMemory(platform, image_infos[i].load_address,
1085+
pointer_size,
1086+
image_infos[i].macho_info)) {
1087+
image_infos[i].is_valid_mach_header = true;
1088+
}
11771089
}
11781090
}
1179-
return FormatDynamicLibrariesIntoJSON(image_infos);
1091+
return FormatDynamicLibrariesIntoJSON(image_infos, report_load_commands);
11801092
}
11811093

11821094
// Fetch information about the shared libraries at the given load addresses
@@ -1226,7 +1138,8 @@ static bool mach_header_validity_test(uint32_t magic, uint32_t cputype) {
12261138
image_infos[i].is_valid_mach_header = true;
12271139
}
12281140
}
1229-
return FormatDynamicLibrariesIntoJSON(image_infos);
1141+
return FormatDynamicLibrariesIntoJSON(image_infos,
1142+
/* report_load_commands = */ true);
12301143
}
12311144

12321145
// From dyld's internal podyld_process_info.h:

0 commit comments

Comments
 (0)