1fd98b2af3773437487af0df22c428f3db630949awaylonis// Copyright (c) 2006, Google Inc.
2fd98b2af3773437487af0df22c428f3db630949awaylonis// All rights reserved.
3fd98b2af3773437487af0df22c428f3db630949awaylonis//
4fd98b2af3773437487af0df22c428f3db630949awaylonis// Redistribution and use in source and binary forms, with or without
5fd98b2af3773437487af0df22c428f3db630949awaylonis// modification, are permitted provided that the following conditions are
6fd98b2af3773437487af0df22c428f3db630949awaylonis// met:
7fd98b2af3773437487af0df22c428f3db630949awaylonis//
8fd98b2af3773437487af0df22c428f3db630949awaylonis//     * Redistributions of source code must retain the above copyright
9fd98b2af3773437487af0df22c428f3db630949awaylonis// notice, this list of conditions and the following disclaimer.
10fd98b2af3773437487af0df22c428f3db630949awaylonis//     * Redistributions in binary form must reproduce the above
11fd98b2af3773437487af0df22c428f3db630949awaylonis// copyright notice, this list of conditions and the following disclaimer
12fd98b2af3773437487af0df22c428f3db630949awaylonis// in the documentation and/or other materials provided with the
13fd98b2af3773437487af0df22c428f3db630949awaylonis// distribution.
14fd98b2af3773437487af0df22c428f3db630949awaylonis//     * Neither the name of Google Inc. nor the names of its
15fd98b2af3773437487af0df22c428f3db630949awaylonis// contributors may be used to endorse or promote products derived from
16fd98b2af3773437487af0df22c428f3db630949awaylonis// this software without specific prior written permission.
17fd98b2af3773437487af0df22c428f3db630949awaylonis//
18fd98b2af3773437487af0df22c428f3db630949awaylonis// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19fd98b2af3773437487af0df22c428f3db630949awaylonis// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20fd98b2af3773437487af0df22c428f3db630949awaylonis// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21fd98b2af3773437487af0df22c428f3db630949awaylonis// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22fd98b2af3773437487af0df22c428f3db630949awaylonis// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23fd98b2af3773437487af0df22c428f3db630949awaylonis// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24fd98b2af3773437487af0df22c428f3db630949awaylonis// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25fd98b2af3773437487af0df22c428f3db630949awaylonis// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26fd98b2af3773437487af0df22c428f3db630949awaylonis// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27fd98b2af3773437487af0df22c428f3db630949awaylonis// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28fd98b2af3773437487af0df22c428f3db630949awaylonis// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29e5dc60822e5938fea2ae892ccddb906641ba174emmentovai
30fd98b2af3773437487af0df22c428f3db630949awaylonis// macho_walker.h: Iterate over the load commands in a mach-o file
31fd98b2af3773437487af0df22c428f3db630949awaylonis//
32fd98b2af3773437487af0df22c428f3db630949awaylonis// Author: Dan Waylonis
33fd98b2af3773437487af0df22c428f3db630949awaylonis
34fd98b2af3773437487af0df22c428f3db630949awaylonis#ifndef COMMON_MAC_MACHO_WALKER_H__
35fd98b2af3773437487af0df22c428f3db630949awaylonis#define COMMON_MAC_MACHO_WALKER_H__
36fd98b2af3773437487af0df22c428f3db630949awaylonis
37b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.org#include <mach/machine.h>
38fd98b2af3773437487af0df22c428f3db630949awaylonis#include <mach-o/loader.h>
39fd98b2af3773437487af0df22c428f3db630949awaylonis#include <sys/types.h>
40fd98b2af3773437487af0df22c428f3db630949awaylonis
41fd98b2af3773437487af0df22c428f3db630949awaylonisnamespace MacFileUtilities {
42fd98b2af3773437487af0df22c428f3db630949awaylonis
43fd98b2af3773437487af0df22c428f3db630949awaylonisclass MachoWalker {
44fd98b2af3773437487af0df22c428f3db630949awaylonis public:
45fd98b2af3773437487af0df22c428f3db630949awaylonis  // A callback function executed when a new load command is read.  If no
46fd98b2af3773437487af0df22c428f3db630949awaylonis  // further processing of load commands is desired, return false.  Otherwise,
47fd98b2af3773437487af0df22c428f3db630949awaylonis  // return true.
48fd98b2af3773437487af0df22c428f3db630949awaylonis  // |cmd| is the current command, and |offset| is the location relative to the
49fd98b2af3773437487af0df22c428f3db630949awaylonis  // beginning of the file (not header) where the command was read.  If |swap|
50fd98b2af3773437487af0df22c428f3db630949awaylonis  // is set, then any command data (other than the returned load_command) should
51fd98b2af3773437487af0df22c428f3db630949awaylonis  // be swapped when read
52fd98b2af3773437487af0df22c428f3db630949awaylonis  typedef bool (*LoadCommandCallback)(MachoWalker *walker, load_command *cmd,
53fd98b2af3773437487af0df22c428f3db630949awaylonis                                      off_t offset, bool swap, void *context);
54fd98b2af3773437487af0df22c428f3db630949awaylonis
55fd98b2af3773437487af0df22c428f3db630949awaylonis  MachoWalker(const char *path, LoadCommandCallback callback, void *context);
568fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org  MachoWalker(void *memory, size_t size, LoadCommandCallback callback,
578fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org              void *context);
58fd98b2af3773437487af0df22c428f3db630949awaylonis  ~MachoWalker();
59fd98b2af3773437487af0df22c428f3db630949awaylonis
60b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.org  // Begin walking the header for |cpu_type| and |cpu_subtype|.  If |cpu_type|
61b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.org  // is 0, then the native cpu type is used. Otherwise, accepted values are
62b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.org  // listed in /usr/include/mach/machine.h (e.g., CPU_TYPE_X86 or
63b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.org  // CPU_TYPE_POWERPC). If |cpu_subtype| is CPU_SUBTYPE_MULTIPLE, the match is
64b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.org  // only done on |cpu_type|.
65b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.org  // Returns false if opening the file failed or if the |cpu_type|/|cpu_subtype|
66b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.org  // is not present in the file.
67b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.org  bool WalkHeader(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype);
68fd98b2af3773437487af0df22c428f3db630949awaylonis
69fd98b2af3773437487af0df22c428f3db630949awaylonis  // Read |size| bytes from the opened file at |offset| into |buffer|
70fd98b2af3773437487af0df22c428f3db630949awaylonis  bool ReadBytes(void *buffer, size_t size, off_t offset);
718fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org
72983264848d5372d8e64d62eb67f672c71e4b6470waylonis  // Return the current header and header offset
73983264848d5372d8e64d62eb67f672c71e4b6470waylonis  bool CurrentHeader(struct mach_header_64 *header, off_t *offset);
74fd98b2af3773437487af0df22c428f3db630949awaylonis
75fd98b2af3773437487af0df22c428f3db630949awaylonis private:
76b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.org  // Locate (if any) the header offset for |cpu_type| and return in |offset|.
77b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.org  // Return true if found, false otherwise.
78b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.org  bool FindHeader(cpu_type_t cpu_type,
79b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.org                  cpu_subtype_t cpu_subtype,
80b2cb7ad7bc83205d23f77b660438bf8e8d16fcb5qsr@chromium.org                  off_t &offset);
81fd98b2af3773437487af0df22c428f3db630949awaylonis
82fd98b2af3773437487af0df22c428f3db630949awaylonis  // Process an individual header starting at |offset| from the start of the
83fd98b2af3773437487af0df22c428f3db630949awaylonis  // file.  Return true if successful, false otherwise.
84fd98b2af3773437487af0df22c428f3db630949awaylonis  bool WalkHeaderAtOffset(off_t offset);
85fd98b2af3773437487af0df22c428f3db630949awaylonis  bool WalkHeader64AtOffset(off_t offset);
86fd98b2af3773437487af0df22c428f3db630949awaylonis
87fd98b2af3773437487af0df22c428f3db630949awaylonis  // Bottleneck for walking the load commands
88fd98b2af3773437487af0df22c428f3db630949awaylonis  bool WalkHeaderCore(off_t offset, uint32_t number_of_commands, bool swap);
89fd98b2af3773437487af0df22c428f3db630949awaylonis
90fd98b2af3773437487af0df22c428f3db630949awaylonis  // File descriptor to the opened file
91fd98b2af3773437487af0df22c428f3db630949awaylonis  int file_;
92fd98b2af3773437487af0df22c428f3db630949awaylonis
938fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org  // Memory location to read from.
948fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org  void *memory_;
958fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org
968fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org  // Size of the memory segment we can read from.
978fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org  size_t memory_size_;
988fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org
99fd98b2af3773437487af0df22c428f3db630949awaylonis  // User specified callback & context
100fd98b2af3773437487af0df22c428f3db630949awaylonis  LoadCommandCallback callback_;
101fd98b2af3773437487af0df22c428f3db630949awaylonis  void *callback_context_;
1028fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org
103983264848d5372d8e64d62eb67f672c71e4b6470waylonis  // Current header, size, and offset.  The mach_header_64 is used for both
104983264848d5372d8e64d62eb67f672c71e4b6470waylonis  // 32-bit and 64-bit headers because they only differ in their last field
1058fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org  // (reserved).  By adding the |current_header_size_| and the
106983264848d5372d8e64d62eb67f672c71e4b6470waylonis  // |current_header_offset_|, you can determine the offset in the file just
107983264848d5372d8e64d62eb67f672c71e4b6470waylonis  // after the header.
108983264848d5372d8e64d62eb67f672c71e4b6470waylonis  struct mach_header_64 *current_header_;
109983264848d5372d8e64d62eb67f672c71e4b6470waylonis  unsigned long current_header_size_;
110983264848d5372d8e64d62eb67f672c71e4b6470waylonis  off_t current_header_offset_;
1118fac6df2a0dfbfe7512c3f6616cda4cbac4f0d9dqsr@chromium.org
1124ac61acb3a7dad6ce722fe07564be8ec92713228dmaclach private:
1134ac61acb3a7dad6ce722fe07564be8ec92713228dmaclach  MachoWalker(const MachoWalker &);
1144ac61acb3a7dad6ce722fe07564be8ec92713228dmaclach  MachoWalker &operator=(const MachoWalker &);
115fd98b2af3773437487af0df22c428f3db630949awaylonis};
116fd98b2af3773437487af0df22c428f3db630949awaylonis
117fd98b2af3773437487af0df22c428f3db630949awaylonis}  // namespace MacFileUtilities
118fd98b2af3773437487af0df22c428f3db630949awaylonis
119fd98b2af3773437487af0df22c428f3db630949awaylonis#endif  // COMMON_MAC_MACHO_WALKER_H__
120