1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2009-2012 Apple Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
22 * @APPLE_LICENSE_HEADER_END@
33 #include <sys/syslimits.h>
34 #include <mach-o/arch.h>
35 #include <mach-o/loader.h>
36 #include <mach/mach.h>
41 #include "dsc_iterator.h"
42 #include "dyld_cache_format.h"
43 #include "Architectures.hpp"
44 #include "MachOFileAbstraction.hpp"
45 #include "CacheFileAbstraction.hpp"
60 const char* dependentsOfPath
;
61 const void* mappedCache
;
64 bool printDylibVersions
;
73 struct TextInfoSorter
{
74 bool operator()(const TextInfo
& left
, const TextInfo
& right
) {
75 return (left
.textSize
> right
.textSize
);
80 std::map
<uint32_t, const char*> pageToContent
;
81 uint64_t linkeditBase
;
82 bool dependentTargetFound
;
83 std::vector
<TextInfo
> textSegments
;
89 fprintf(stderr
, "Usage: dyld_shared_cache_util -list [ -uuid ] [-vmaddr] | -dependents <dylib-path> [ -versions ] | -linkedit | -map [ shared-cache-file ] | -slide_info | -info\n");
93 static bool isHaswell()
95 // check system is capable of running x86_64h code
96 struct host_basic_info info
;
97 mach_msg_type_number_t count
= HOST_BASIC_INFO_COUNT
;
98 mach_port_t hostPort
= mach_host_self();
99 kern_return_t result
= host_info(hostPort
, HOST_BASIC_INFO
, (host_info_t
)&info
, &count
);
100 mach_port_deallocate(mach_task_self(), hostPort
);
101 if ( result
!= KERN_SUCCESS
)
103 return ( info
.cpu_subtype
== CPU_SUBTYPE_X86_64_H
);
108 * Get the path to the native shared cache for this host
110 static const char* default_shared_cache_path() {
112 return MACOSX_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME
"i386";
115 return MACOSX_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME
"x86_64h";
117 return MACOSX_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME
"x86_64";
118 #elif __ARM_ARCH_5TEJ__
119 return IPHONE_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME
"armv5";
120 #elif __ARM_ARCH_6K__
121 return IPHONE_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME
"armv6";
122 #elif __ARM_ARCH_7K__
123 return IPHONE_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME
"armv7k";
124 #elif __ARM_ARCH_7A__
125 return IPHONE_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME
"armv7";
126 #elif __ARM_ARCH_7F__
127 return IPHONE_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME
"armv7f";
128 #elif __ARM_ARCH_7S__
129 return IPHONE_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME
"armv7s";
131 return IPHONE_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME
"arm64";
133 #error unsupported architecture
137 typedef void (*segment_callback_t
)(const dyld_shared_cache_dylib_info
* dylibInfo
, const dyld_shared_cache_segment_info
* segInfo
,
138 const Options
& options
, Results
& results
);
143 * List dependencies from the mach-o header at headerAddr
144 * in the same format as 'otool -L'
146 template <typename A
>
147 void print_dependencies(const dyld_shared_cache_dylib_info
* dylibInfo
, const dyld_shared_cache_segment_info
* segInfo
,
148 const Options
& options
, Results
& results
) {
149 typedef typename
A::P P
;
150 typedef typename
A::P::E E
;
152 if ( strcmp(options
.dependentsOfPath
, dylibInfo
->path
) != 0 )
154 if ( strcmp(segInfo
->name
, "__TEXT") != 0 )
157 const macho_dylib_command
<P
>* dylib_cmd
;
158 const macho_header
<P
>* mh
= (const macho_header
<P
>*)dylibInfo
->machHeader
;
159 const macho_load_command
<P
>* const cmds
= (macho_load_command
<P
>*)((uintptr_t)dylibInfo
->machHeader
+ sizeof(macho_header
<P
>));
160 const uint32_t cmd_count
= mh
->ncmds();
161 const macho_load_command
<P
>* cmd
= cmds
;
162 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
163 switch ( cmd
->cmd() ) {
166 case LC_REEXPORT_DYLIB
:
167 case LC_LOAD_WEAK_DYLIB
:
168 case LC_LOAD_UPWARD_DYLIB
:
169 dylib_cmd
= (macho_dylib_command
<P
>*)cmd
;
170 if ( options
.printDylibVersions
) {
171 uint32_t compat_vers
= dylib_cmd
->compatibility_version();
172 uint32_t current_vers
= dylib_cmd
->current_version();
173 printf("\t%s", dylib_cmd
->name());
174 if ( compat_vers
!= 0xFFFFFFFF ) {
175 printf("(compatibility version %u.%u.%u, current version %u.%u.%u)\n",
177 (compat_vers
>> 8) & 0xff,
178 (compat_vers
) & 0xff,
179 (current_vers
>> 16),
180 (current_vers
>> 8) & 0xff,
181 (current_vers
) & 0xff);
188 printf("\t%s\n", dylib_cmd
->name());
192 cmd
= (const macho_load_command
<P
>*)(((uint8_t*)cmd
)+cmd
->cmdsize());
194 results
.dependentTargetFound
= true;
198 * Print out a dylib from the shared cache, optionally including the UUID or unslid load address
200 template <typename A
>
201 void print_list(const dyld_shared_cache_dylib_info
* dylibInfo
, const dyld_shared_cache_segment_info
* segInfo
,
202 const Options
& options
, Results
& results
)
204 if ( strcmp(segInfo
->name
, "__TEXT") != 0 )
207 if ( options
.printVMAddrs
)
208 printf("0x%08llX ", segInfo
->address
);
209 if ( options
.printInodes
)
210 printf("0x%08llX 0x%08llX ", dylibInfo
->inode
, dylibInfo
->modTime
);
211 if ( options
.printUUIDs
) {
212 if ( dylibInfo
->uuid
!= NULL
) {
213 const uint8_t* uuid
= (uint8_t*)dylibInfo
->uuid
;;
214 printf("<%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X> ",
215 uuid
[0], uuid
[1], uuid
[2], uuid
[3],
216 uuid
[4], uuid
[5], uuid
[6], uuid
[7],
217 uuid
[8], uuid
[9], uuid
[10], uuid
[11],
218 uuid
[12], uuid
[13], uuid
[14], uuid
[15]);
221 printf("< no uuid in dylib > ");
223 if ( dylibInfo
->isAlias
)
224 printf("[alias] %s\n", dylibInfo
->path
);
226 printf("%s\n", dylibInfo
->path
);
230 template <typename A
>
231 void collect_size(const dyld_shared_cache_dylib_info
* dylibInfo
, const dyld_shared_cache_segment_info
* segInfo
,
232 const Options
& options
, Results
& results
)
234 if ( strcmp(segInfo
->name
, "__TEXT") != 0 )
236 if ( dylibInfo
->isAlias
)
240 info
.textSize
= segInfo
->fileSize
;
241 info
.path
= dylibInfo
->path
;
242 results
.textSegments
.push_back(info
);
243 size_t size
= segInfo
->fileSize
;
249 static void add_linkedit(uint32_t pageStart
, uint32_t pageEnd
, const char* message
, Results
& results
)
251 for (uint32_t p
= pageStart
; p
<= pageEnd
; p
+= 4096) {
252 std::map
<uint32_t, const char*>::iterator pos
= results
.pageToContent
.find(p
);
253 if ( pos
== results
.pageToContent
.end() ) {
254 results
.pageToContent
[p
] = strdup(message
);
257 const char* oldMessage
= pos
->second
;
259 asprintf(&newMesssage
, "%s, %s", oldMessage
, message
);
260 results
.pageToContent
[p
] = newMesssage
;
261 ::free((void*)oldMessage
);
268 * get LINKEDIT info for dylib
270 template <typename A
>
271 void process_linkedit(const dyld_shared_cache_dylib_info
* dylibInfo
, const dyld_shared_cache_segment_info
* segInfo
,
272 const Options
& options
, Results
& results
) {
273 typedef typename
A::P P
;
274 typedef typename
A::P::E E
;
275 // filter out symlinks
276 if ( dylibInfo
->isAlias
)
278 const macho_header
<P
>* mh
= (const macho_header
<P
>*)dylibInfo
->machHeader
;
279 uint32_t ncmds
= mh
->ncmds();
280 const macho_load_command
<P
>* const cmds
= (macho_load_command
<P
>*)((long)mh
+ sizeof(macho_header
<P
>));
281 const macho_load_command
<P
>* cmd
= cmds
;
282 for (uint32_t i
= 0; i
< ncmds
; i
++) {
283 if ( cmd
->cmd() == LC_DYLD_INFO_ONLY
) {
284 macho_dyld_info_command
<P
>* dyldInfo
= (macho_dyld_info_command
<P
>*)cmd
;
286 const char* shortName
= strrchr(dylibInfo
->path
, '/') + 1;
287 // add export trie info
288 if ( dyldInfo
->export_size() != 0 ) {
289 //printf("export_off=0x%X\n", dyldInfo->export_off());
290 uint32_t exportPageOffsetStart
= dyldInfo
->export_off() & (-4096);
291 uint32_t exportPageOffsetEnd
= (dyldInfo
->export_off() + dyldInfo
->export_size()) & (-4096);
292 sprintf(message
, "exports from %s", shortName
);
293 add_linkedit(exportPageOffsetStart
, exportPageOffsetEnd
, message
, results
);
296 if ( dyldInfo
->bind_size() != 0 ) {
297 uint32_t bindPageOffsetStart
= dyldInfo
->bind_off() & (-4096);
298 uint32_t bindPageOffsetEnd
= (dyldInfo
->bind_off() + dyldInfo
->bind_size()) & (-4096);
299 sprintf(message
, "bindings from %s", shortName
);
300 add_linkedit(bindPageOffsetStart
, bindPageOffsetEnd
, message
, results
);
302 // add lazy binding info
303 if ( dyldInfo
->lazy_bind_size() != 0 ) {
304 uint32_t lazybindPageOffsetStart
= dyldInfo
->lazy_bind_off() & (-4096);
305 uint32_t lazybindPageOffsetEnd
= (dyldInfo
->lazy_bind_off() + dyldInfo
->lazy_bind_size()) & (-4096);
306 sprintf(message
, "lazy bindings from %s", shortName
);
307 add_linkedit(lazybindPageOffsetStart
, lazybindPageOffsetEnd
, message
, results
);
309 // add weak binding info
310 if ( dyldInfo
->weak_bind_size() != 0 ) {
311 uint32_t weakbindPageOffsetStart
= dyldInfo
->weak_bind_off() & (-4096);
312 uint32_t weakbindPageOffsetEnd
= (dyldInfo
->weak_bind_off() + dyldInfo
->weak_bind_size()) & (-4096);
313 sprintf(message
, "weak bindings from %s", shortName
);
314 add_linkedit(weakbindPageOffsetStart
, weakbindPageOffsetEnd
, message
, results
);
317 cmd
= (const macho_load_command
<P
>*)(((uint8_t*)cmd
)+cmd
->cmdsize());
323 * Print out a .map file similar to what update_dyld_shared_cache created when the cache file was built
325 template <typename A
>
326 void print_map(const dyld_shared_cache_dylib_info
* dylibInfo
, const dyld_shared_cache_segment_info
* segInfo
, const Options
& options
, Results
& results
) {
327 if ( !dylibInfo
->isAlias
)
328 printf("0x%08llX - 0x%08llX %s %s\n", segInfo
->address
, segInfo
->address
+ segInfo
->fileSize
, segInfo
->name
, dylibInfo
->path
);
332 static void checkMode(Mode mode
) {
333 if ( mode
!= modeNone
) {
334 fprintf(stderr
, "Error: select one of: -list, -dependents, -info, -slide_info, -linkedit, -map, or -size\n");
340 int main (int argc
, const char* argv
[]) {
342 const char* sharedCachePath
= default_shared_cache_path();
345 options
.mode
= modeNone
;
346 options
.printUUIDs
= false;
347 options
.printVMAddrs
= false;
348 options
.printDylibVersions
= false;
349 options
.printInodes
= false;
350 options
.dependentsOfPath
= NULL
;
352 for (uint32_t i
= 1; i
< argc
; i
++) {
353 const char* opt
= argv
[i
];
355 if (strcmp(opt
, "-list") == 0) {
356 checkMode(options
.mode
);
357 options
.mode
= modeList
;
359 else if (strcmp(opt
, "-dependents") == 0) {
360 checkMode(options
.mode
);
361 options
.mode
= modeDependencies
;
362 options
.dependentsOfPath
= argv
[++i
];
364 fprintf(stderr
, "Error: option -depdendents requires an argument\n");
369 else if (strcmp(opt
, "-linkedit") == 0) {
370 checkMode(options
.mode
);
371 options
.mode
= modeLinkEdit
;
373 else if (strcmp(opt
, "-info") == 0) {
374 checkMode(options
.mode
);
375 options
.mode
= modeInfo
;
377 else if (strcmp(opt
, "-slide_info") == 0) {
378 checkMode(options
.mode
);
379 options
.mode
= modeSlideInfo
;
381 else if (strcmp(opt
, "-map") == 0) {
382 checkMode(options
.mode
);
383 options
.mode
= modeMap
;
385 else if (strcmp(opt
, "-size") == 0) {
386 checkMode(options
.mode
);
387 options
.mode
= modeSize
;
389 else if (strcmp(opt
, "-uuid") == 0) {
390 options
.printUUIDs
= true;
392 else if (strcmp(opt
, "-inode") == 0) {
393 options
.printInodes
= true;
395 else if (strcmp(opt
, "-versions") == 0) {
396 options
.printDylibVersions
= true;
398 else if (strcmp(opt
, "-vmaddr") == 0) {
399 options
.printVMAddrs
= true;
402 fprintf(stderr
, "Error: unrecognized option %s\n", opt
);
408 sharedCachePath
= opt
;
412 if ( options
.mode
== modeNone
) {
413 fprintf(stderr
, "Error: select one of -list, -dependents, -info, -linkedit, or -map\n");
418 if ( options
.mode
!= modeSlideInfo
) {
419 if ( options
.printUUIDs
&& (options
.mode
!= modeList
) )
420 fprintf(stderr
, "Warning: -uuid option ignored outside of -list mode\n");
422 if ( options
.printVMAddrs
&& (options
.mode
!= modeList
) )
423 fprintf(stderr
, "Warning: -vmaddr option ignored outside of -list mode\n");
425 if ( options
.printDylibVersions
&& (options
.mode
!= modeDependencies
) )
426 fprintf(stderr
, "Warning: -versions option ignored outside of -dependents mode\n");
428 if ( (options
.mode
== modeDependencies
) && (options
.dependentsOfPath
== NULL
) ) {
429 fprintf(stderr
, "Error: -dependents given, but no dylib path specified\n");
436 if ( ::stat(sharedCachePath
, &statbuf
) == -1 ) {
437 fprintf(stderr
, "Error: stat() failed for dyld shared cache at %s, errno=%d\n", sharedCachePath
, errno
);
441 int cache_fd
= ::open(sharedCachePath
, O_RDONLY
);
442 if ( cache_fd
< 0 ) {
443 fprintf(stderr
, "Error: open() failed for shared cache file at %s, errno=%d\n", sharedCachePath
, errno
);
446 options
.mappedCache
= ::mmap(NULL
, statbuf
.st_size
, PROT_READ
, MAP_PRIVATE
, cache_fd
, 0);
447 if (options
.mappedCache
== MAP_FAILED
) {
448 fprintf(stderr
, "Error: mmap() for shared cache at %s failed, errno=%d\n", sharedCachePath
, errno
);
452 if ( options
.mode
== modeSlideInfo
) {
453 const dyldCacheHeader
<LittleEndian
>* header
= (dyldCacheHeader
<LittleEndian
>*)options
.mappedCache
;
454 if ( header
->slideInfoOffset() == 0 ) {
455 fprintf(stderr
, "Error: dyld shared cache does not contain slide info\n");
458 const dyldCacheFileMapping
<LittleEndian
>* mappings
= (dyldCacheFileMapping
<LittleEndian
>*)((char*)options
.mappedCache
+ header
->mappingOffset());
459 const dyldCacheFileMapping
<LittleEndian
>* dataMapping
= &mappings
[1];
460 uint64_t dataStartAddress
= dataMapping
->address();
461 uint64_t dataSize
= dataMapping
->size();
462 const dyldCacheSlideInfo
<LittleEndian
>* slideInfoHeader
= (dyldCacheSlideInfo
<LittleEndian
>*)((char*)options
.mappedCache
+header
->slideInfoOffset());
463 printf("slide info version=%d\n", slideInfoHeader
->version());
464 printf("toc_count=%d, data page count=%lld\n", slideInfoHeader
->toc_count(), dataSize
/4096);
465 const dyldCacheSlideInfoEntry
* entries
= (dyldCacheSlideInfoEntry
*)((char*)slideInfoHeader
+ slideInfoHeader
->entries_offset());
466 for(int i
=0; i
< slideInfoHeader
->toc_count(); ++i
) {
467 printf("0x%08llX: [% 5d,% 5d] ", dataStartAddress
+ i
*4096, i
, slideInfoHeader
->toc(i
));
468 const dyldCacheSlideInfoEntry
* entry
= &entries
[slideInfoHeader
->toc(i
)];
469 for(int j
=0; j
< slideInfoHeader
->entries_size(); ++j
)
470 printf("%02X", entry
->bits
[j
]);
474 else if ( options
.mode
== modeInfo
) {
475 const dyldCacheHeader
<LittleEndian
>* header
= (dyldCacheHeader
<LittleEndian
>*)options
.mappedCache
;
477 if ( header
->mappingOffset() >= 0x68 ) {
478 const uint8_t* uuid
= header
->uuid();
479 printf("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X\n",
480 uuid
[0], uuid
[1], uuid
[2], uuid
[3],
481 uuid
[4], uuid
[5], uuid
[6], uuid
[7],
482 uuid
[8], uuid
[9], uuid
[10], uuid
[11],
483 uuid
[12], uuid
[13], uuid
[14], uuid
[15]);
488 printf("image count: %u\n", header
->imagesCount());
489 printf("mappings:\n");
490 const dyldCacheFileMapping
<LittleEndian
>* mappings
= (dyldCacheFileMapping
<LittleEndian
>*)((char*)options
.mappedCache
+ header
->mappingOffset());
491 for (uint32_t i
=0; i
< header
->mappingCount(); ++i
) {
492 if ( mappings
[i
].init_prot() & VM_PROT_EXECUTE
)
493 printf(" __TEXT %3lluMB, 0x%08llX -> 0x%08llX\n", mappings
[i
].size()/(1024*1024), mappings
[i
].address(), mappings
[i
].address() + mappings
[i
].size());
494 else if ( mappings
[i
]. init_prot() & VM_PROT_WRITE
)
495 printf(" __DATA %3lluMB, 0x%08llX -> 0x%08llX\n", mappings
[i
].size()/(1024*1024), mappings
[i
].address(), mappings
[i
].address() + mappings
[i
].size());
496 else if ( mappings
[i
].init_prot() & VM_PROT_READ
)
497 printf(" __LINKEDIT %3lluMB, 0x%08llX -> 0x%08llX\n", mappings
[i
].size()/(1024*1024), mappings
[i
].address(), mappings
[i
].address() + mappings
[i
].size());
499 if ( header
->codeSignatureOffset() != 0 ) {
500 uint64_t size
= statbuf
.st_size
- header
->codeSignatureOffset();
501 uint64_t csAddr
= mappings
[header
->mappingCount()-1].address() + mappings
[header
->mappingCount()-1].size();
502 printf(" code sign %3lluMB, 0x%08llX -> 0x%08llX\n", size
/(1024*1024), csAddr
, csAddr
+ size
);
506 segment_callback_t callback
;
507 if ( strcmp((char*)options
.mappedCache
, "dyld_v1 i386") == 0 ) {
508 switch ( options
.mode
) {
510 callback
= print_list
<x86
>;
513 callback
= print_map
<x86
>;
515 case modeDependencies
:
516 callback
= print_dependencies
<x86
>;
519 callback
= process_linkedit
<x86
>;
522 callback
= collect_size
<x86
>;
530 else if ( (strcmp((char*)options
.mappedCache
, "dyld_v1 x86_64") == 0)
531 || (strcmp((char*)options
.mappedCache
, "dyld_v1 x86_64h") == 0) ) {
532 switch ( options
.mode
) {
534 callback
= print_list
<x86_64
>;
537 callback
= print_map
<x86_64
>;
539 case modeDependencies
:
540 callback
= print_dependencies
<x86_64
>;
543 callback
= process_linkedit
<x86_64
>;
546 callback
= collect_size
<x86_64
>;
554 else if ( (strncmp((char*)options
.mappedCache
, "dyld_v1 armv", 14) == 0)
555 || (strncmp((char*)options
.mappedCache
, "dyld_v1 armv", 13) == 0) ) {
556 switch ( options
.mode
) {
558 callback
= print_list
<arm
>;
561 callback
= print_map
<arm
>;
563 case modeDependencies
:
564 callback
= print_dependencies
<arm
>;
567 callback
= process_linkedit
<arm
>;
570 callback
= collect_size
<arm
>;
578 else if ( strcmp((char*)options
.mappedCache
, "dyld_v1 arm64") == 0 ) {
579 switch ( options
.mode
) {
581 callback
= print_list
<arm64
>;
584 callback
= print_map
<arm64
>;
586 case modeDependencies
:
587 callback
= print_dependencies
<arm64
>;
590 callback
= process_linkedit
<arm64
>;
593 callback
= collect_size
<arm64
>;
602 fprintf(stderr
, "Error: unrecognized dyld shared cache magic.\n");
606 __block Results results
;
607 results
.dependentTargetFound
= false;
608 int iterateResult
= dyld_shared_cache_iterate(options
.mappedCache
, (uint32_t)statbuf
.st_size
,
609 ^(const dyld_shared_cache_dylib_info
* dylibInfo
, const dyld_shared_cache_segment_info
* segInfo
) {
610 (callback
)(dylibInfo
, segInfo
, options
, results
);
612 if ( iterateResult
!= 0 ) {
613 fprintf(stderr
, "Error: malformed shared cache file\n");
617 if ( options
.mode
== modeLinkEdit
) {
618 // dump -linkedit information
619 for (std::map
<uint32_t, const char*>::iterator it
= results
.pageToContent
.begin(); it
!= results
.pageToContent
.end(); ++it
) {
620 printf("0x%08X %s\n", it
->first
, it
->second
);
623 else if ( options
.mode
== modeSize
) {
624 std::sort(results
.textSegments
.begin(), results
.textSegments
.end(), TextInfoSorter());
625 for (std::vector
<TextInfo
>::iterator it
= results
.textSegments
.begin(); it
!= results
.textSegments
.end(); ++it
) {
626 printf(" 0x%08llX %s\n", it
->textSize
, it
->path
);
630 if ( (options
.mode
== modeDependencies
) && options
.dependentsOfPath
&& !results
.dependentTargetFound
) {
631 fprintf(stderr
, "Error: could not find '%s' in the shared cache at\n %s\n", options
.dependentsOfPath
, sharedCachePath
);