1/*
2 * Copyright (c) 2006-2008, 2012 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28#ifndef __MACHO_UTIL_H__
29#define __MACHO_UTIL_H__
30
31#include <mach-o/loader.h>
32#include <mach-o/nlist.h>
33#include <uuid/uuid.h>
34
35/*******************************************************************************
36********************************************************************************
37**                   DO NOT USE THIS API. IT IS VOLATILE.                     **
38********************************************************************************
39*******************************************************************************/
40
41/*! @header macho_util
42Handy functions for working with Mach-O files. Very rudimentary, use at your
43own risk.
44*/
45
46/*!
47 * @define  MAGIC32
48 * @abstract  Get the 32-bit magic number from a file data pointer.
49 * @param ptr A pointer to a file whose magic number you want to get.
50 * @result    Returns an unsigned 32-bit integer containing
51 *            the first four bytes of the file data.
52 */
53#define MAGIC32(ptr)          (*((uint32_t *)(ptr)))
54
55#define ISMACHO(magic)        (((magic) == MH_MAGIC) || \
56                               ((magic) == MH_CIGAM) || \
57                               ((magic) == MH_MAGIC_64) || \
58                               ((magic) == MH_CIGAM_64))
59#define ISSWAPPEDMACHO(magic)  (((magic) == MH_CIGAM) || \
60                               ((magic) == MH_CIGAM_64))
61#define ISMACHO64(magic)      (((magic) == MH_MAGIC_64) || \
62                               ((magic) == MH_CIGAM_64))
63
64/*******************************************************************************
65*
66*******************************************************************************/
67#define CondSwapInt32(flag, value)  ((flag) ? OSSwapInt32((value)) : \
68                                    (uint32_t)(value))
69#define CondSwapInt64(flag, value)  ((flag) ? OSSwapInt64((value)) : \
70                                    (uint64_t)(value))
71/*!
72 * @enum macho_seek_result
73 * @abstract Results of a lookup within a Mach-O file.
74 * @discussion This enum lists the possible return values for a Mach-O lookup.
75 * @constant macho_seek_result_error Invalid arguments or bad Mach-O file.
76 * @constant macho_seek_result_found The requested item was found.
77 * @constant macho_seek_result_not_found The requested item was not found.
78 *           For functions called repeatedly (such as the macho_lc_callback),
79 *           this means the item may be found on a subsequent invocation.
80 * @constant macho_seek_result_stop The requested item will not be found.
81 *           This is only returned by functions that may be called repeatedly,
82 *           when they can determine conclusively that the requested item does not exist.
83 */
84typedef enum {
85    macho_seek_result_error          = -1,
86    macho_seek_result_found          = 0,
87    macho_seek_result_found_no_value = 1,
88    macho_seek_result_not_found      = 2,
89    macho_seek_result_stop           = 3,
90} macho_seek_result;
91
92/*!
93 * @function macho_find_symbol
94 * @abstract Finds symbol data in a mapped Mach-O file.
95 * @discussion
96 *        The macho_find_symbol function searches a memory-mapped Mach-O file
97 *        for a given symbol,
98 *        indirectly returning the address within that mapped file
99 *        containing the data for that symbol.
100 *        Only symbols of type N_SECT, N_UNDF result in an address;
101 *        for N_ABS and N_INDR the result will be macho_seek_result_found_no_value.
102 * @param file_start A pointer to the beginning of the mapped Mach-O file.
103 * @param file_end A pointer to the end of the mapped Mach-O file.
104 * @param name The name of the symbol to find.
105 * @param nlist_type The address of a uint8_t that will be filled with the type
106 *        of the located symbol.
107 * @param symbol_address The address of a pointer that will be filled
108 *        with the location of the symbol's data in the mapped file,
109 *        if the address can be calculated.
110 * @result Returns macho_seek_result_found if the symbol is found,
111 * macho_seek_result_not_found if the symbol is not defined in the given file,
112 * or macho_seek_result_error if an error occurs.
113 */
114macho_seek_result macho_find_symbol(
115    const void          * file_start,
116    const void          * file_end,
117    const char          * name,
118          uint8_t       * nlist_type,
119    const void         ** symbol_address);
120
121/*!
122 * @function macho_find_symtab
123 * @abstract Finds a mapped Mach-O file's symbol table.
124 * @discussion
125 *        The macho_find_symtab function locates the symbol table of a Mach-O
126 *        file. Only the LC_SYMTAB load command is located, not the LC_DSYMTAB.
127 * @param mach_header A pointer to the beginning of the mapped Mach-O file.
128 * @param file_end A pointer to the end of the mapped Mach-O file.
129 * @param symtab A pointer to the address of a symtab_command struct;
130 *        if provided, this is filled with the address of the file's symbol table.
131 * @result Returns macho_seek_result_found if the symbol table is found,
132 * macho_seek_result_not_found if a symbol table is not defined in the given file,
133 * or macho_seek_result_error if an error occurs.
134 */
135macho_seek_result macho_find_symtab(
136    const void             * file_start,
137    const void             * file_end,
138    struct symtab_command ** symtab);
139
140/*!
141 * @function macho_find_dysymtab
142 * @abstract Finds a mapped Mach-O file's dynamic link-edit symbol table info.
143 * @discussion
144 *        The macho_find_dysymtab function locates the dynamic link-edit symbol
145 *        table of a Mach-O file. Only the LC_DYSYMTAB load command is located,
146 *        not the LC_SYMTAB.
147 * @param mach_header A pointer to the beginning of the mapped Mach-O file.
148 * @param file_end A pointer to the end of the mapped Mach-O file.
149 * @param dysymtab A pointer to the address of a dysymtab_command struct;
150 *        if provided, this is filled with the address of the file's symbol table.
151 * @result Returns macho_seek_result_found if the symbol table is found,
152 * macho_seek_result_not_found if a symbol table is not defined in the given file,
153 * or macho_seek_result_error if an error occurs.
154 */
155macho_seek_result macho_find_dysymtab(
156                                      const void               * file_start,
157                                      const void               * file_end,
158                                      struct dysymtab_command ** dysymtab);
159
160/*!
161 * @function macho_find_uuid
162 * @abstract Finds a mapped Mach-O file's UUID.
163 * @discussion
164 *        The macho_find_uuid function locates the UUID of a Mach-O file.
165 * @param mach_header A pointer to the beginning of the mapped Mach-O file.
166 * @param file_end A pointer to the end of the mapped Mach-O file.
167 * @param uuid A pointer to the start of the UUID bytes;
168 *        if provided, this is filled with the address of the UUID bytes.
169 * @result Returns macho_seek_result_found if the UUID is found,
170 * macho_seek_result_not_found if a UUID is not defined in the given file,
171 * or macho_seek_result_error if an error occurs.
172 */
173macho_seek_result macho_find_uuid(
174    const void * file_start,
175    const void * file_end,
176    char       **uuid);
177
178/*!
179 * @function macho_find_section_numbered
180 * @abstract Finds an ordinal section in a Mach-O file.
181 * @discussion
182 *        The macho_find_section_numbered function locates an ordinally-numbered
183 *        section within a Mach-O file, which is needed for calculating proper
184 *        offsets and addresses of such things as nlist entries.
185 *        Sections are numbered in a Mach-O file starting with 1, since zero
186 *        is reserved to mean "no section".
187 *        Since you will likely be passing a section number directly from other
188 *        structure within the same Mach-O file, this should not be a problem.
189 * @param mach_header A pointer to the beginning of the mapped Mach-O file.
190 * @param file_end A pointer to the end of the mapped Mach-O file.
191 * @param sect_num The ordinal number of the section to get, starting with 1.
192 * @result Returns a pointer to the requested section struct if it exists;
193 *         otherwise returns NULL.
194 */
195// cast to (struct section[_64] *)
196void * macho_find_section_numbered(
197    const void * file_start,
198    const void * file_end,
199    uint8_t sect_num);
200
201/*!
202 * @typedef macho_lc_callback
203 * @abstract The callback function used when scanning Mach-O load commands
204 *           with macho_scan_load_commands.
205 * @discussion macho_lc_callback defines the callback function
206 * invoked by macho_scan_load_commands for each load command it encounters.
207 * The scan function passes a pointer to a user data struct that you can use
208 * for search parameters, running information, and search results.
209 * @param load_command A pointer to the Mach-O load command being processed.
210 * @param file_end A pointer to the end of the mapped Mach-O file,
211 *        to be used for bounds checking.
212 * @param swap A boolean flag indicating whether the Mach-O file's byte order
213 *        is opposite the host's.
214 *        If nonzero, the callback needs to swap all multibyte values
215 *        read from the Mach-O file.
216 * @param user_data A pointer to user-defined data that is passed unaltered
217 *        across invocations of the callback function.
218 * @result Returns macho_seek_result_found if the requested item is found,
219 * macho_seek_result_not_found if is not found on this call,
220 * macho_seek_result_stop if the function determined that it does not exist,
221 * or macho_seek_result_error if an error occurs
222 * (particularly if any data structure to be accessed
223 * would run past the end of the file).
224 */
225typedef macho_seek_result (*macho_lc_callback)(
226    struct load_command * load_command,
227    const void          * file_end,
228    uint8_t               swap,
229    void                * user_data
230);
231
232/*!
233 * @function macho_find_source_version
234 * @abstract Finds a mapped Mach-O file's LC_SOURCE_VERSION.
235 * @discussion
236 *        The macho_find_source_version function locates the source version
237 *        load command of a Mach-O file.
238 * @param mach_header A pointer to the beginning of the mapped Mach-O file.
239 * @param file_end A pointer to the end of the mapped Mach-O file.
240 * @param version A pointer to a uint64_t variable into which to store the
241 *        contents of the 'version' field of the LC_SOURCE_VERSION load
242 *        command from the mach-o header.
243 * @result Returns macho_seek_result_found if the source version is found,
244 * macho_seek_result_not_found if a source version is not defined in the
245 * given file, or macho_seek_result_error if an error occurs.
246 */
247macho_seek_result macho_find_source_version(
248                                            const void * file_start,
249                                            const void * file_end,
250                                            uint64_t   * version);
251
252/*!
253 * @function macho_scan_load_commands
254 * @abstract Iterates over the load commands of a Mach-O file using a callback.
255 * @discussion
256 *        The macho_scan_load_commands iterates over the load commands within a
257 *        Mach-O file, invoking a user-supplied callback until that callback
258 *        returns a result indicating the scan should stop.
259 * @param mach_header A pointer to the beginning of the mapped Mach-O file.
260 * @param file_end A pointer to the end of the mapped Mach-O file.
261 * @param lc_callback A function that is invoked on each load command
262 *        of the Mach-O file until the callback function
263 *        indicates the scan is finished.
264 * @param user_data A pointer to user-defined data that is passed unaltered
265 *        across invocations of the callback function.
266 * @result Returns a pointer to the requested section struct if it exists;
267 *         otherwise returns NULL.
268 */
269macho_seek_result macho_scan_load_commands(
270    const void        * file_start,
271    const void        * file_end,
272    macho_lc_callback   lc_callback,
273    void              * user_data);
274
275boolean_t macho_swap(
276    u_char            * file);
277
278boolean_t macho_unswap(
279    u_char            * file);
280
281struct segment_command * macho_get_segment_by_name(
282    struct mach_header    * mach_header,
283    const char            * segname);
284
285struct segment_command_64 * macho_get_segment_by_name_64(
286    struct mach_header_64      * mach_header,
287    const char                 * segname);
288
289struct section * macho_get_section_by_name(
290    struct mach_header    * mach_header,
291    const char            * segname,
292    const char            * sectname);
293
294struct section_64 * macho_get_section_by_name_64(
295    struct mach_header_64     * mach_header,
296    const char                * segname,
297    const char                * sectname);
298
299boolean_t macho_remove_linkedit(
300    u_char    * macho,
301    u_long    * linkedit_size);
302
303boolean_t macho_trim_linkedit(
304    u_char    *macho,
305    u_long    *amount_trimmed);
306
307#endif /* __MACHO_UTIL_H__ */
308