1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include <AvailabilityMacros.h>
7 #include <mach-o/loader.h>
8 #include <mach-o/dyld_images.h>
9 #include <mach/task_info.h>
10 #include <mach/task.h>
11 #include <mach/mach_init.h>
12 #include <mach/mach_traps.h>
18 #include "shared-libraries.h"
20 #ifndef MAC_OS_X_VERSION_10_6
21 #define MAC_OS_X_VERSION_10_6 1060
24 #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
25 // borrowed from Breakpad
26 // Fallback declarations for TASK_DYLD_INFO and friends, introduced in
27 // <mach/task_info.h> in the Mac OS X 10.6 SDK.
28 #define TASK_DYLD_INFO 17
29 struct task_dyld_info
{
30 mach_vm_address_t all_image_info_addr
;
31 mach_vm_size_t all_image_info_size
;
33 typedef struct task_dyld_info task_dyld_info_data_t
;
34 typedef struct task_dyld_info
*task_dyld_info_t
;
35 #define TASK_DYLD_INFO_COUNT (sizeof(task_dyld_info_data_t) / sizeof(natural_t))
39 // Architecture specific abstraction.
41 typedef mach_header platform_mach_header
;
42 typedef segment_command mach_segment_command_type
;
43 #define MACHO_MAGIC_NUMBER MH_MAGIC
44 #define CMD_SEGMENT LC_SEGMENT
45 #define seg_size uint32_t
47 typedef mach_header_64 platform_mach_header
;
48 typedef segment_command_64 mach_segment_command_type
;
49 #define MACHO_MAGIC_NUMBER MH_MAGIC_64
50 #define CMD_SEGMENT LC_SEGMENT_64
51 #define seg_size uint64_t
55 void addSharedLibrary(const platform_mach_header
* header
, char *name
, SharedLibraryInfo
&info
) {
56 const struct load_command
*cmd
=
57 reinterpret_cast<const struct load_command
*>(header
+ 1);
60 unsigned long long start
= reinterpret_cast<unsigned long long>(header
);
61 // Find the cmd segment in the macho image. It will contain the offset we care about.
62 const uint8_t *uuid_bytes
= nullptr;
63 for (unsigned int i
= 0;
64 cmd
&& (i
< header
->ncmds
) && (uuid_bytes
== nullptr || size
== 0);
66 if (cmd
->cmd
== CMD_SEGMENT
) {
67 const mach_segment_command_type
*seg
=
68 reinterpret_cast<const mach_segment_command_type
*>(cmd
);
70 if (!strcmp(seg
->segname
, "__TEXT")) {
73 } else if (cmd
->cmd
== LC_UUID
) {
74 const uuid_command
*ucmd
= reinterpret_cast<const uuid_command
*>(cmd
);
75 uuid_bytes
= ucmd
->uuid
;
78 cmd
= reinterpret_cast<const struct load_command
*>
79 (reinterpret_cast<const char *>(cmd
) + cmd
->cmdsize
);
82 std::stringstream uuid
;
83 uuid
<< std::hex
<< std::uppercase
;
84 if (uuid_bytes
!= nullptr) {
85 for (int i
= 0; i
< 16; ++i
) {
86 uuid
<< ((uuid_bytes
[i
] & 0xf0) >> 4);
87 uuid
<< (uuid_bytes
[i
] & 0xf);
92 info
.AddSharedLibrary(SharedLibrary(start
, start
+ size
, 0, uuid
.str(),
96 // Use dyld to inspect the macho image information. We can build the SharedLibraryEntry structure
97 // giving us roughtly the same info as /proc/PID/maps in Linux.
98 SharedLibraryInfo
SharedLibraryInfo::GetInfoForSelf()
100 SharedLibraryInfo sharedLibraryInfo
;
102 task_dyld_info_data_t task_dyld_info
;
103 mach_msg_type_number_t count
= TASK_DYLD_INFO_COUNT
;
104 if (task_info(mach_task_self (), TASK_DYLD_INFO
, (task_info_t
)&task_dyld_info
,
105 &count
) != KERN_SUCCESS
) {
106 return sharedLibraryInfo
;
109 struct dyld_all_image_infos
* aii
= (struct dyld_all_image_infos
*)task_dyld_info
.all_image_info_addr
;
110 size_t infoCount
= aii
->infoArrayCount
;
112 // Iterate through all dyld images (loaded libraries) to get their names
114 for (size_t i
= 0; i
< infoCount
; ++i
) {
115 const dyld_image_info
*info
= &aii
->infoArray
[i
];
117 // If the magic number doesn't match then go no further
118 // since we're not pointing to where we think we are.
119 if (info
->imageLoadAddress
->magic
!= MACHO_MAGIC_NUMBER
) {
123 const platform_mach_header
* header
=
124 reinterpret_cast<const platform_mach_header
*>(info
->imageLoadAddress
);
126 // Add the entry for this image.
127 addSharedLibrary(header
, (char*)info
->imageFilePath
, sharedLibraryInfo
);
130 return sharedLibraryInfo
;