@@ -37,16 +37,15 @@ class MemoryMappingLayoutMock final : public MemoryMappingLayout {
37
37
.uuid = {}
38
38
};
39
39
40
- static constexpr char dylib_name[] = " libclang_rt.\0\0\0 " ; // 8 bytes aligned, padded with zeros per loader.h
40
+ static constexpr char libclang_rt_dylib_name[] =
41
+ " libclang_rt.\0\0\0 " ; // 8 bytes aligned, padded with zeros per loader.h
42
+ static constexpr char uninstrumented_dylib_name[] =
43
+ " uninst___rt.\0\0\0 " ; // 8 bytes aligned, padded with zeros per loader.h
44
+
41
45
static constexpr dylib_command mock_dylib_command = {
42
- .cmd = LC_LOAD_DYLIB,
43
- .cmdsize = sizeof (dylib_command) + sizeof (dylib_name),
44
- .dylib = {
45
- .name = {
46
- .offset = sizeof (dylib_command)
47
- }
48
- }
49
- };
46
+ .cmd = LC_LOAD_DYLIB,
47
+ .cmdsize = sizeof (dylib_command) + sizeof (libclang_rt_dylib_name),
48
+ .dylib = {.name = {.offset = sizeof (dylib_command)}}};
50
49
51
50
static constexpr uuid_command mock_trap_command = {
52
51
.cmd = LC_UUID,
@@ -59,51 +58,57 @@ class MemoryMappingLayoutMock final : public MemoryMappingLayout {
59
58
std::vector<unsigned char > mock_header;
60
59
61
60
public:
62
- MemoryMappingLayoutMock (): MemoryMappingLayout(false ) {
63
- EXPECT_EQ (mock_uuid_command.cmdsize % 8 , 0u );
64
- EXPECT_EQ (mock_dylib_command.cmdsize % 8 , 0u );
65
-
66
- Reset ();
67
-
68
- #ifdef MH_MAGIC_64
69
- const struct mach_header_64 *header = (mach_header_64 *)_dyld_get_image_header (0 ); // Any header will do
70
- const size_t header_size = sizeof (mach_header_64);
71
- #else
72
- const struct mach_header *header = _dyld_get_image_header (0 );
73
- const size_t header_size = sizeof (mach_header);
74
- #endif
75
- const size_t mock_header_size_with_extras = header_size + header->sizeofcmds +
76
- mock_uuid_command.cmdsize + mock_dylib_command.cmdsize + sizeof (uuid_command);
77
-
78
- mock_header.reserve (mock_header_size_with_extras);
79
- // Copy the original header
80
- copy ((unsigned char *)header,
81
- (unsigned char *)header + header_size + header->sizeofcmds ,
82
- back_inserter (mock_header));
83
- // The following commands are not supposed to be processed
84
- // by the (correct) ::Next method at all, since they're not
85
- // accounted for in header->ncmds .
86
- copy ((unsigned char *)&mock_uuid_command,
87
- ((unsigned char *)&mock_uuid_command) + mock_uuid_command.cmdsize ,
88
- back_inserter (mock_header));
89
- copy ((unsigned char *)&mock_dylib_command,
90
- ((unsigned char *)&mock_dylib_command) + sizeof (dylib_command), // as mock_dylib_command.cmdsize contains the following string
91
- back_inserter (mock_header));
92
- copy ((unsigned char *)dylib_name,
93
- ((unsigned char *)dylib_name) + sizeof (dylib_name),
94
- back_inserter (mock_header));
95
-
96
- // Append a command w. huge size to have the test detect the read overrun
97
- copy ((unsigned char *)&mock_trap_command,
98
- ((unsigned char *)&mock_trap_command) + sizeof (uuid_command),
99
- back_inserter (mock_header));
100
-
101
- start_load_cmd_addr = (const char *)(mock_header.data () + header_size);
102
- sizeofcmds = header->sizeofcmds ;
103
-
104
- const char *last_byte_load_cmd_addr = (start_load_cmd_addr+sizeofcmds-1 );
105
- data_.current_image = -1 ; // So the loop in ::Next runs just once
106
- }
61
+ MemoryMappingLayoutMock (bool instrumented) : MemoryMappingLayout(false ) {
62
+ EXPECT_EQ (mock_uuid_command.cmdsize % 8 , 0u );
63
+ EXPECT_EQ (mock_dylib_command.cmdsize % 8 , 0u );
64
+
65
+ Reset ();
66
+
67
+ # ifdef MH_MAGIC_64
68
+ const struct mach_header_64 *header =
69
+ (mach_header_64 *)_dyld_get_image_header (0 ); // Any header will do
70
+ const size_t header_size = sizeof (mach_header_64);
71
+ # else
72
+ const struct mach_header *header = _dyld_get_image_header (0 );
73
+ const size_t header_size = sizeof (mach_header);
74
+ # endif
75
+ const size_t mock_header_size_with_extras =
76
+ header_size + header->sizeofcmds + mock_uuid_command.cmdsize +
77
+ mock_dylib_command.cmdsize + sizeof (uuid_command);
78
+
79
+ mock_header.reserve (mock_header_size_with_extras);
80
+ // Copy the original header
81
+ copy ((unsigned char *)header,
82
+ (unsigned char *)header + header_size + header->sizeofcmds ,
83
+ back_inserter (mock_header));
84
+ // The following commands are not supposed to be processed
85
+ // by the (correct) ::Next method at all, since they're not
86
+ // accounted for in header->ncmds .
87
+ copy ((unsigned char *)&mock_uuid_command,
88
+ ((unsigned char *)&mock_uuid_command) + mock_uuid_command.cmdsize ,
89
+ back_inserter (mock_header));
90
+ copy ((unsigned char *)&mock_dylib_command,
91
+ ((unsigned char *)&mock_dylib_command) +
92
+ sizeof (dylib_command), // as mock_dylib_command.cmdsize contains
93
+ // the following string
94
+ back_inserter (mock_header));
95
+ const char (&dylib_name)[16 ] =
96
+ instrumented ? libclang_rt_dylib_name : uninstrumented_dylib_name;
97
+ copy ((unsigned char *)dylib_name,
98
+ ((unsigned char *)dylib_name) + sizeof (dylib_name),
99
+ back_inserter (mock_header));
100
+
101
+ // Append a command w. huge size to have the test detect the read overrun
102
+ copy ((unsigned char *)&mock_trap_command,
103
+ ((unsigned char *)&mock_trap_command) + sizeof (uuid_command),
104
+ back_inserter (mock_header));
105
+
106
+ start_load_cmd_addr = (const char *)(mock_header.data () + header_size);
107
+ sizeofcmds = header->sizeofcmds ;
108
+
109
+ const char *last_byte_load_cmd_addr = (start_load_cmd_addr + sizeofcmds - 1 );
110
+ data_.current_image = -1 ; // So the loop in ::Next runs just once
111
+ }
107
112
108
113
size_t SizeOfLoadCommands () {
109
114
return sizeofcmds;
@@ -120,8 +125,20 @@ class MemoryMappingLayoutMock final : public MemoryMappingLayout {
120
125
}
121
126
};
122
127
123
- TEST (MemoryMappingLayout, Next) {
124
- __sanitizer::MemoryMappingLayoutMock memory_mapping;
128
+ TEST (MemoryMappingLayout, NextInstrumented) {
129
+ __sanitizer::MemoryMappingLayoutMock memory_mapping (true );
130
+ __sanitizer::MemoryMappedSegment segment;
131
+ size_t size = memory_mapping.SizeOfLoadCommands ();
132
+ while (memory_mapping.Next (&segment)) {
133
+ size_t offset = memory_mapping.CurrentLoadCommandOffset ();
134
+ EXPECT_LE (offset, size);
135
+ }
136
+ size_t final_offset = memory_mapping.CurrentLoadCommandOffset ();
137
+ EXPECT_EQ (final_offset, size); // All commands processed, no more, no less
138
+ }
139
+
140
+ TEST (MemoryMappingLayout, NextUnInstrumented) {
141
+ __sanitizer::MemoryMappingLayoutMock memory_mapping (false );
125
142
__sanitizer::MemoryMappedSegment segment;
126
143
size_t size = memory_mapping.SizeOfLoadCommands ();
127
144
while (memory_mapping.Next (&segment)) {
0 commit comments