19
19
#include < sstream>
20
20
#include < string>
21
21
#include < unordered_map>
22
-
22
+ # include < sys/procfs.h >
23
23
#include " NativeThreadAIX.h"
24
24
#include " Plugins/Process/POSIX/ProcessPOSIXLog.h"
25
25
// #include "Plugins/Process/Utility/LinuxProcMaps.h"
@@ -79,6 +79,7 @@ using namespace lldb_private;
79
79
using namespace lldb_private ::process_aix;
80
80
using namespace llvm ;
81
81
82
+ typedef std::function<bool (llvm::Expected<MemoryRegionInfo>)> AIXMapCallback;
82
83
// Private bits we only need internally.
83
84
84
85
static bool ProcessVmReadvSupported () {
@@ -988,13 +989,6 @@ Status NativeProcessAIX::GetMemoryRegionInfo(lldb::addr_t load_addr,
988
989
for (auto it = m_mem_region_cache.begin (); it != m_mem_region_cache.end ();
989
990
++it) {
990
991
MemoryRegionInfo &proc_entry_info = it->first ;
991
-
992
- // Sanity check assumption that /proc/{pid}/maps entries are ascending.
993
- assert ((proc_entry_info.GetRange ().GetRangeBase () >= prev_base_address) &&
994
- " descending /proc/pid/maps entries detected, unexpected" );
995
- prev_base_address = proc_entry_info.GetRange ().GetRangeBase ();
996
- UNUSED_IF_ASSERT_DISABLED (prev_base_address);
997
-
998
992
// If the target address comes before this entry, indicate distance to next
999
993
// region.
1000
994
if (load_addr < proc_entry_info.GetRange ().GetRangeBase ()) {
@@ -1029,9 +1023,59 @@ Status NativeProcessAIX::GetMemoryRegionInfo(lldb::addr_t load_addr,
1029
1023
return error;
1030
1024
}
1031
1025
1026
+ // Parsing the AIX map file /proc/PID/map
1027
+ // The map file contains an array of prmap structures
1028
+ // which has all the information like size, startaddress, object name, permissions
1029
+ bool ParseAIXMapRegions (const char *aix_map, AIXMapCallback const &callback) {
1030
+ MemoryRegionInfo region;
1031
+ struct prmap *prmapData = (struct prmap *)aix_map;
1032
+ struct prmap *entry;
1033
+ uint32_t perm_flag;
1034
+
1035
+ for (entry = prmapData;!(entry->pr_size == 0 && entry->pr_vaddr == NULL ); entry++) {
1036
+ const char *o_name = aix_map + entry->pr_pathoff ;
1037
+ lldb::addr_t start_address = (lldb::addr_t )entry->pr_vaddr ;
1038
+ lldb::addr_t end_address = start_address + entry->pr_size ;
1039
+ region.GetRange ().SetRangeBase (start_address);
1040
+ region.GetRange ().SetRangeEnd (end_address);
1041
+ region.SetMapped (MemoryRegionInfo::OptionalBool::eYes);
1042
+ perm_flag = entry->pr_mflags ;
1043
+
1044
+ if (perm_flag & MA_READ)
1045
+ region.SetReadable (MemoryRegionInfo::OptionalBool::eYes);
1046
+ else
1047
+ region.SetReadable (MemoryRegionInfo::OptionalBool::eNo);
1048
+
1049
+ if (perm_flag & MA_WRITE)
1050
+ region.SetWritable (MemoryRegionInfo::OptionalBool::eYes);
1051
+ else
1052
+ region.SetWritable (MemoryRegionInfo::OptionalBool::eNo);
1053
+
1054
+ if (perm_flag & MA_EXEC)
1055
+ region.SetExecutable (MemoryRegionInfo::OptionalBool::eYes);
1056
+ else
1057
+ region.SetExecutable (MemoryRegionInfo::OptionalBool::eNo);
1058
+
1059
+ if ((perm_flag & MA_SLIBTEXT) || (perm_flag & MA_SLIBDATA))
1060
+ region.SetShared (MemoryRegionInfo::OptionalBool::eYes);
1061
+ else if ((perm_flag & MA_PLIBTEXT) || (perm_flag & MA_PLIBDATA))
1062
+ region.SetShared (MemoryRegionInfo::OptionalBool::eNo);
1063
+ else
1064
+ region.SetShared (MemoryRegionInfo::OptionalBool::eDontKnow);
1065
+
1066
+ if (o_name)
1067
+ region.SetName (o_name);
1068
+
1069
+ callback (region);
1070
+ region.Clear ();
1071
+ }
1072
+
1073
+ return true ;
1074
+ }
1075
+
1076
+
1032
1077
Status NativeProcessAIX::PopulateMemoryRegionCache () {
1033
1078
Log *log = GetLog (POSIXLog::Process);
1034
-
1035
1079
// If our cache is empty, pull the latest. There should always be at least
1036
1080
// one memory region if memory region handling is supported.
1037
1081
if (!m_mem_region_cache.empty ()) {
@@ -1041,7 +1085,7 @@ Status NativeProcessAIX::PopulateMemoryRegionCache() {
1041
1085
}
1042
1086
1043
1087
Status Result;
1044
- # if 0
1088
+
1045
1089
AIXMapCallback callback = [&](llvm::Expected<MemoryRegionInfo> Info) {
1046
1090
if (Info) {
1047
1091
FileSpec file_spec (Info->GetName ().GetCString ());
@@ -1050,26 +1094,17 @@ Status NativeProcessAIX::PopulateMemoryRegionCache() {
1050
1094
return true ;
1051
1095
}
1052
1096
1053
- Result = Info.takeError();
1097
+ Result = Status::FromError ( Info.takeError () );
1054
1098
m_supports_mem_region = LazyBool::eLazyBoolNo;
1055
1099
LLDB_LOG (log, " failed to parse proc maps: {0}" , Result);
1056
1100
return false ;
1057
1101
};
1058
1102
1059
- // AIX kernel since 2.6.14 has /proc/{pid}/smaps
1060
- // if CONFIG_PROC_PAGE_MONITOR is enabled
1061
- auto BufferOrError = getProcFile(GetID(), GetCurrentThreadID(), "smaps");
1062
- if (BufferOrError)
1063
- ParseAIXSMapRegions(BufferOrError.get()->getBuffer(), callback);
1064
- else {
1065
- BufferOrError = getProcFile(GetID(), GetCurrentThreadID(), "maps");
1066
- if (!BufferOrError) {
1067
- m_supports_mem_region = LazyBool::eLazyBoolNo;
1068
- return BufferOrError.getError();
1069
- }
1070
-
1071
- ParseAIXMapRegions(BufferOrError.get()->getBuffer(), callback);
1072
- }
1103
+ auto BufferOrError = getProcFile (GetID (), " map" );
1104
+ if (BufferOrError) {
1105
+ std::unique_ptr<llvm::MemoryBuffer> MapBuffer = std::move (*BufferOrError);
1106
+ ParseAIXMapRegions (MapBuffer->getBufferStart (), callback);
1107
+ }
1073
1108
1074
1109
if (Result.Fail ())
1075
1110
return Result;
@@ -1090,7 +1125,7 @@ Status NativeProcessAIX::PopulateMemoryRegionCache() {
1090
1125
1091
1126
// We support memory retrieval, remember that.
1092
1127
m_supports_mem_region = LazyBool::eLazyBoolYes;
1093
- # endif
1128
+
1094
1129
return Status ();
1095
1130
}
1096
1131
0 commit comments