aadsm created this revision. aadsm added reviewers: clayborg, xiaobai. Herald added subscribers: lldb-commits, krytarowski, srhines. Herald added a project: LLDB. aadsm added a parent revision: D62501: Implement GetSharedLibraryInfoAddress. aadsm added a child revision: D62503: Add ReadCStringFromMemory for faster string reads.
This is the fourth patch to improve module loading in a series that started here (where I explain the motivation and solution): D62499 <https://reviews.llvm.org/D62499> Implement the `xfer:libraries-svr4` packet by adding a new function that generates the list and then in Handle_xfer I generate the XML for it. The XML is really simple so I'm just using string concatenation because I believe it's more readable than having to deal with a DOM api. Concerns -------- - I'm not sure about the having the ELFLinkMap and the SharedLibraryInfo struct in there. I thought about creating a function or class outside of NativeProcessLinux so it could be reusable in other contexts but the core functions need to use ReadMemory so it was not convinent and I guess would have forced me to pass a lambda as a wrapper to ReadMemory. This would introduce more complexity to the code and I'm not sure if it would be worthwhile. - On Handle_xfer function the backing buffer structure uses MemoryBuffers so I had to create one out of the StreamString response I generate with the XML. This kind of sucks because I'm copying all this data when I usually don't even need it. And if I do need it still sucks because I'm copying something that I just generated right there. I couldn't find a way to generate the XML into a MemoryBuffer (as it requires to know the size before hand) or use another structure that would make this easier. I've thought about changing the backing structure to StringRefs but that object doesn't really own the underlying "const char*" so I can't keep it without copying again. Any suggestions here? Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D62502 Files: lldb/include/lldb/Host/common/NativeProcessProtocol.h lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp lldb/source/Plugins/Process/Linux/NativeProcessLinux.h lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp =================================================================== --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -2760,6 +2760,28 @@ #else return SendUnimplementedResponse("not implemented on this platform"); #endif + } else if (xfer_object == "libraries-svr4") { +#if defined(__linux__) + std::vector<SharedLibraryInfo> library_list; + auto error = + m_debugged_process_up->GetLoadedSharedLibraries(library_list); + if (!error.Success()) + return SendErrorResponse(error.GetError()); + + StreamString response; + response.Printf("<library-list-svr4 version=\"1.0\">"); + for (auto const &library : library_list) { + response.Printf("<library name=\"%s\" ", library.name.c_str()); + response.Printf("lm=\"0x%" PRIx64 "\" ", library.link_map); + response.Printf("l_addr=\"0x%" PRIx64 "\" ", library.base_addr); + response.Printf("l_ld=\"0x%" PRIx64 "\" />", library.ld_addr); + } + response.Printf("</library-list-svr4>"); + memory_buffer_sp = std::move( + MemoryBuffer::getMemBufferCopy(response.GetString(), __FUNCTION__)); +#else + return SendUnimplementedResponse("not implemented on this platform"); +#endif } else return SendUnimplementedResponse("Xfer object not supported"); } Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp =================================================================== --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -826,6 +826,9 @@ response.PutCString(";QPassSignals+"); response.PutCString(";qXfer:auxv:read+"); #endif +#if defined(__linux__) + response.PutCString(";qXfer:libraries-svr4:read+"); +#endif return SendPacketNoLock(response.GetString()); } Index: lldb/source/Plugins/Process/Linux/NativeProcessLinux.h =================================================================== --- lldb/source/Plugins/Process/Linux/NativeProcessLinux.h +++ lldb/source/Plugins/Process/Linux/NativeProcessLinux.h @@ -79,6 +79,9 @@ lldb::addr_t GetSharedLibraryInfoAddress() override; + Status GetLoadedSharedLibraries( + std::vector<SharedLibraryInfo> &library_list) override; + size_t UpdateThreads() override; const ArchSpec &GetArchitecture() const override { return m_arch; } @@ -133,6 +136,17 @@ template <typename ELF_EHDR, typename ELF_PHDR, typename ELF_DYN> lldb::addr_t GetELFImageInfoAddress(); + template <typename T> struct ELFLinkMap { + T l_addr; + T l_name; + T l_ld; + T l_next; + T l_prev; + }; + template <typename T> + Status ReadSharedLibraryInfo(lldb::addr_t link_map_addr, + SharedLibraryInfo &info); + private: MainLoop::SignalHandleUP m_sigchld_handle; ArchSpec m_arch; Index: lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp =================================================================== --- lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -2169,3 +2169,76 @@ return LLDB_INVALID_ADDRESS; } + +template <typename T> +Status NativeProcessLinux::ReadSharedLibraryInfo(lldb::addr_t link_map_addr, + SharedLibraryInfo &info) { + ELFLinkMap<T> link_map; + size_t bytes_read; + auto error = + ReadMemory(link_map_addr, &link_map, sizeof(link_map), bytes_read); + if (!error.Success()) + return error; + + char name_buffer[PATH_MAX]; + error = ReadMemory(link_map.l_name, &name_buffer, sizeof(name_buffer), + bytes_read); + if (!error.Success()) + return error; + + info.name = std::string(name_buffer); + info.link_map = link_map_addr; + info.base_addr = link_map.l_addr; + info.ld_addr = link_map.l_ld; + info.next = link_map.l_next; +#if defined(__linux__) && !defined(__ANDROID__) + // On non-android linux systems, main executable has an empty path. + info.main = info.main.empty(); +#elif defined(__linux__) && defined(__ANDROID__) + // On android, the main executable has a load address of 0. + info.main = info.ld_addr == 0; +#else + info.main = false; +#endif + + return Status(); +} + +Status NativeProcessLinux::GetLoadedSharedLibraries( + std::vector<SharedLibraryInfo> &library_list) { + // Address of DT_DEBUG.d_ptr which points to r_debug + lldb::addr_t info_address = GetSharedLibraryInfoAddress(); + if (info_address == LLDB_INVALID_ADDRESS) + return Status("Invalid shared library info address"); + // Address of r_debug + lldb::addr_t address = 0; + size_t bytes_read; + auto error = + ReadMemory(info_address, &address, GetAddressByteSize(), bytes_read); + if (!error.Success()) + return error; + if (address == 0) + return Status("Invalid r_debug address"); + // Read r_debug.r_map + lldb::addr_t link_map = 0; + error = ReadMemory(address + GetAddressByteSize(), &link_map, + GetAddressByteSize(), bytes_read); + if (!error.Success()) + return error; + if (address == 0) + return Status("Invalid link_map address"); + + while (link_map) { + SharedLibraryInfo info; + if (GetAddressByteSize() == 8) + error = ReadSharedLibraryInfo<uint64_t>(link_map, info); + else + error = ReadSharedLibraryInfo<uint32_t>(link_map, info); + if (!error.Success()) + return error; + library_list.push_back(info); + link_map = info.next; + } + + return Status(); +} Index: lldb/include/lldb/Host/common/NativeProcessProtocol.h =================================================================== --- lldb/include/lldb/Host/common/NativeProcessProtocol.h +++ lldb/include/lldb/Host/common/NativeProcessProtocol.h @@ -32,6 +32,15 @@ class MemoryRegionInfo; class ResumeActionList; +struct SharedLibraryInfo { + std::string name; + lldb::addr_t link_map; + lldb::addr_t base_addr; + lldb::addr_t ld_addr; + bool main; + lldb::addr_t next; +}; + // NativeProcessProtocol class NativeProcessProtocol { public: @@ -86,6 +95,11 @@ virtual lldb::addr_t GetSharedLibraryInfoAddress() = 0; + virtual Status + GetLoadedSharedLibraries(std::vector<SharedLibraryInfo> &library_list) { + return Status("Not implemented"); + } + virtual bool IsAlive() const; virtual size_t UpdateThreads() = 0;
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits