Skip to content

Commit 25c92ff

Browse files
committed
Fix AMD module path parsing to work for memory modules.
1 parent 9ce3e95 commit 25c92ff

File tree

1 file changed

+75
-62
lines changed

1 file changed

+75
-62
lines changed

lldb/tools/lldb-server/Plugins/AMDGPU/ProcessAMDGPU.cpp

Lines changed: 75 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -141,45 +141,75 @@ bool ProcessAMDGPU::GetProcessInfo(ProcessInstanceInfo &proc_info) {
141141
return true;
142142
}
143143

144-
static std::pair<std::string, std::pair<uint64_t, uint64_t>>
145-
ParsePathname(const std::string &pathname) {
146-
std::string file_path;
147-
uint64_t offset = 0;
148-
uint64_t size = 0;
149-
150-
// Find the position of #offset=
151-
size_t offset_pos = pathname.find("#offset=");
152-
if (offset_pos != std::string::npos) {
153-
// Extract the file path (remove file:// prefix if present)
154-
std::string path = pathname.substr(0, offset_pos);
155-
if (path.find("file://") == 0) {
156-
file_path = path.substr(7); // Remove "file://"
157-
} else {
158-
file_path = path;
159-
}
160-
161-
// Extract offset
162-
size_t size_pos = pathname.find("&size=", offset_pos);
163-
if (size_pos != std::string::npos) {
164-
std::string offset_str =
165-
pathname.substr(offset_pos + 8, size_pos - (offset_pos + 8));
166-
std::string size_str = pathname.substr(size_pos + 6);
167-
168-
offset = std::stoull(offset_str);
169-
size = std::stoull(size_str);
144+
std::optional<lldb_private::GPUDynamicLoaderLibraryInfo>
145+
ParseLibraryInfo(llvm::StringRef lib_spec) {
146+
// This function will parse the shared library string that AMDs GPU driver
147+
// sends to the debugger. The format is one of:
148+
// file://<path>#offset=<file-offset>&size=<file-size>
149+
// memory://<name>#offset=<image-addr>&size=<image-size>
150+
lldb_private::GPUDynamicLoaderLibraryInfo lib_info;
151+
lib_info.load = true;
152+
153+
auto get_offset_and_size = [](llvm::StringRef &values,
154+
std::optional<uint64_t> &offset,
155+
std::optional<uint64_t> &size) {
156+
offset = std::nullopt;
157+
size = std::nullopt;
158+
llvm::StringRef value;
159+
uint64_t uint_value;
160+
std::tie(value, values) = values.split('&');
161+
while (!value.empty()) {
162+
if (value.consume_front("offset=")) {
163+
if (!value.getAsInteger(0, uint_value))
164+
offset = uint_value;
165+
} else if (value.consume_front("size=")) {
166+
if (!value.getAsInteger(0, uint_value))
167+
size = uint_value;
168+
}
169+
std::tie(value, values) = values.split('&');
170170
}
171+
};
172+
173+
if (lib_spec.consume_front("file://")) {
174+
llvm::StringRef path, values;
175+
std::tie(path, values) = lib_spec.split('#');
176+
if (path.empty())
177+
return std::nullopt;
178+
get_offset_and_size(values, lib_info.file_offset, lib_info.file_size);
179+
} else if (lib_spec.consume_front("memory://")) {
180+
llvm::StringRef name, values;
181+
std::tie(name, values) = lib_spec.split('#');
182+
if (name.empty())
183+
return std::nullopt;
184+
lib_info.pathname = name.str();
185+
get_offset_and_size(values, lib_info.native_memory_address,
186+
lib_info.native_memory_size);
187+
// We must have a valid address and size for memory objects.
188+
if (!(lib_info.native_memory_address.has_value() &&
189+
lib_info.native_memory_size.has_value()))
190+
return std::nullopt;
171191
} else {
172-
// No offset/size parameters, just return the path
173-
if (pathname.find("file://") == 0) {
174-
file_path = pathname.substr(7);
175-
} else {
176-
file_path = pathname;
177-
}
192+
return std::nullopt;
193+
}
194+
// TODO: do we need this expanding into a URL or is this for JSON?
195+
lib_info.pathname.clear();
196+
for (char c : path) {
197+
if (c == '#')
198+
lib_info.pathname += "%23";
199+
else if (c == '$')
200+
lib_info.pathname += "%24";
201+
else if (c == '}')
202+
lib_info.pathname += "%7D";
203+
else if (c == '&')
204+
lib_info.pathname += "&amp;";
205+
else
206+
lib_info.pathname += c;
178207
}
179208

180-
return {file_path, {offset, size}};
209+
return lib_info;
181210
}
182211

212+
183213
std::optional<GPUDynamicLoaderResponse>
184214
ProcessAMDGPU::GetGPUDynamicLoaderLibraryInfos(
185215
const GPUDynamicLoaderArgs &args) {
@@ -196,36 +226,19 @@ ProcessAMDGPU::GetGPUDynamicLoaderLibraryInfos(
196226
// Convert each GPU module to an SVR4LibraryInfo object
197227
for (const auto &[addr, module] : gpu_modules) {
198228
if (module.is_loaded) {
199-
auto file_components = ParsePathname(module.path);
200-
std::string path;
201-
for (char c : file_components.first) {
202-
if (c == '#')
203-
path += "%23";
204-
else if (c == '$')
205-
path += "%24";
206-
else if (c == '}')
207-
path += "%7D";
208-
else if (c == '&')
209-
path += "&amp;";
210-
else
211-
path += c;
229+
if (auto lib_info = ParseLibraryInfo(module.path)) {
230+
LLDB_LOGF(log,
231+
"ProcessAMDGPU::%s() adding library: path=%s, addr=0x%" PRIx64
232+
", offset=%" PRIu64 ", size=%" PRIu64,
233+
__FUNCTION__, lib_info->pathname.c_str(),
234+
lib_info->load_address.value(), lib_info->file_offset.value(),
235+
lib_info->file_size.value());
236+
response.library_infos.push_back(*lib_info);
237+
} else {
238+
LLDB_LOGF(log,
239+
"ProcessAMDGPU::%s() failed to parse module path \"%s\"",
240+
__FUNCTION__, module.path.c_str());
212241
}
213-
214-
GPUDynamicLoaderLibraryInfo lib_info;
215-
lib_info.pathname = path;
216-
lib_info.load = true;
217-
lib_info.load_address = module.base_address;
218-
lib_info.file_offset = file_components.second.first;
219-
lib_info.file_size = file_components.second.second;
220-
221-
LLDB_LOGF(log,
222-
"ProcessAMDGPU::%s() adding library: path=%s, addr=0x%" PRIx64
223-
", offset=%" PRIu64 ", size=%" PRIu64,
224-
__FUNCTION__, lib_info.pathname.c_str(),
225-
lib_info.load_address.value(), lib_info.file_offset.value(),
226-
lib_info.file_size.value());
227-
228-
response.library_infos.push_back(lib_info);
229242
}
230243
}
231244

0 commit comments

Comments
 (0)