/*
* Copyright (c) 2006-2008, 2012 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
#ifndef__MACHO_UTIL_H__
#define__MACHO_UTIL_H__
#include<mach-o/loader.h>
#include<mach-o/nlist.h>
#include<uuid/uuid.h>/*******************************************************************************
********************************************************************************
** DO NOT USE THIS API. IT IS VOLATILE. **
********************************************************************************
*******************************************************************************//*! @header macho_util
Handy functions for working with Mach-O files. Very rudimentary, use at your
own risk.
*//*!
* @define MAGIC32
* @abstract Get the 32-bit magic number from a file data pointer.
* @param ptr A pointer to a file whose magic number you want to get.
* @result Returns an unsigned 32-bit integer containing
* the first four bytes of the file data.
*/
#defineMAGIC32(ptr) (*((uint32_t *)(ptr)))
#defineISMACHO(magic) (((magic) == MH_MAGIC) || \
((magic) == MH_CIGAM) || \
((magic) == MH_MAGIC_64) || \
((magic) == MH_CIGAM_64))
#defineISSWAPPEDMACHO(magic) (((magic) == MH_CIGAM) || \
((magic) == MH_CIGAM_64))
#defineISMACHO64(magic) (((magic) == MH_MAGIC_64) || \
((magic) == MH_CIGAM_64))
/*******************************************************************************
*
*******************************************************************************/
#defineCondSwapInt32(flag, value) ((flag) ? OSSwapInt32((value)) : \
(uint32_t)(value))
#defineCondSwapInt64(flag, value) ((flag) ? OSSwapInt64((value)) : \
(uint64_t)(value))
/*!
* @enum macho_seek_result
* @abstract Results of a lookup within a Mach-O file.
* @discussion This enum lists the possible return values for a Mach-O lookup.
* @constant macho_seek_result_error Invalid arguments or bad Mach-O file.
* @constant macho_seek_result_found The requested item was found.
* @constant macho_seek_result_not_found The requested item was not found.
* For functions called repeatedly (such as the macho_lc_callback),
* this means the item may be found on a subsequent invocation.
* @constant macho_seek_result_stop The requested item will not be found.
* This is only returned by functions that may be called repeatedly,
* when they can determine conclusively that the requested item does not exist.
*/typedefenum {
macho_seek_result_error = -1,
macho_seek_result_found = 0,
macho_seek_result_found_no_value = 1,
macho_seek_result_not_found = 2,
macho_seek_result_stop = 3,
} macho_seek_result;
/*!
* @function macho_find_symbol
* @abstract Finds symbol data in a mapped Mach-O file.
* @discussion
* The macho_find_symbol function searches a memory-mapped Mach-O file
* for a given symbol,
* indirectly returning the address within that mapped file
* containing the data for that symbol.
* Only symbols of type N_SECT, N_UNDF result in an address;
* for N_ABS and N_INDR the result will be macho_seek_result_found_no_value.
* @param file_start A pointer to the beginning of the mapped Mach-O file.
* @param file_end A pointer to the end of the mapped Mach-O file.
* @param name The name of the symbol to find.
* @param nlist_type The address of a uint8_t that will be filled with the type
* of the located symbol.
* @param symbol_address The address of a pointer that will be filled
* with the location of the symbol's data in the mapped file,
* if the address can be calculated.
* @result Returns macho_seek_result_found if the symbol is found,
* macho_seek_result_not_found if the symbol is not defined in the given file,
* or macho_seek_result_error if an error occurs.
*/
macho_seek_result macho_find_symbol(
constvoid * file_start,
constvoid * file_end,
constchar * name,
uint8_t * nlist_type,
constvoid ** symbol_address);
/*!
* @function macho_find_symtab
* @abstract Finds a mapped Mach-O file's symbol table.
* @discussion
* The macho_find_symtab function locates the symbol table of a Mach-O
* file. Only the LC_SYMTAB load command is located, not the LC_DSYMTAB.
* @param mach_header A pointer to the beginning of the mapped Mach-O file.
* @param file_end A pointer to the end of the mapped Mach-O file.
* @param symtab A pointer to the address of a symtab_command struct;
* if provided, this is filled with the address of the file's symbol table.
* @result Returns macho_seek_result_found if the symbol table is found,
* macho_seek_result_not_found if a symbol table is not defined in the given file,
* or macho_seek_result_error if an error occurs.
*/
macho_seek_result macho_find_symtab(
constvoid * file_start,
constvoid * file_end,
struct symtab_command ** symtab);
/*!
* @function macho_find_dysymtab
* @abstract Finds a mapped Mach-O file's dynamic link-edit symbol table info.
* @discussion
* The macho_find_dysymtab function locates the dynamic link-edit symbol
* table of a Mach-O file. Only the LC_DYSYMTAB load command is located,
* not the LC_SYMTAB.
* @param mach_header A pointer to the beginning of the mapped Mach-O file.
* @param file_end A pointer to the end of the mapped Mach-O file.
* @param dysymtab A pointer to the address of a dysymtab_command struct;
* if provided, this is filled with the address of the file's symbol table.
* @result Returns macho_seek_result_found if the symbol table is found,
* macho_seek_result_not_found if a symbol table is not defined in the given file,
* or macho_seek_result_error if an error occurs.
*/
macho_seek_result macho_find_dysymtab(
constvoid * file_start,
constvoid * file_end,
struct dysymtab_command ** dysymtab);
/*!
* @function macho_find_uuid
* @abstract Finds a mapped Mach-O file's UUID.
* @discussion
* The macho_find_uuid function locates the UUID of a Mach-O file.
* @param mach_header A pointer to the beginning of the mapped Mach-O file.
* @param file_end A pointer to the end of the mapped Mach-O file.
* @param uuid A pointer to the start of the UUID bytes;
* if provided, this is filled with the address of the UUID bytes.
* @result Returns macho_seek_result_found if the UUID is found,
* macho_seek_result_not_found if a UUID is not defined in the given file,
* or macho_seek_result_error if an error occurs.
*/
macho_seek_result macho_find_uuid(
constvoid * file_start,
constvoid * file_end,
char **uuid);
/*!
* @function macho_find_section_numbered
* @abstract Finds an ordinal section in a Mach-O file.
* @discussion
* The macho_find_section_numbered function locates an ordinally-numbered
* section within a Mach-O file, which is needed for calculating proper
* offsets and addresses of such things as nlist entries.
* Sections are numbered in a Mach-O file starting with 1, since zero
* is reserved to mean "no section".
* Since you will likely be passing a section number directly from other
* structure within the same Mach-O file, this should not be a problem.
* @param mach_header A pointer to the beginning of the mapped Mach-O file.
* @param file_end A pointer to the end of the mapped Mach-O file.
* @param sect_num The ordinal number of the section to get, starting with 1.
* @result Returns a pointer to the requested section struct if it exists;
* otherwise returns NULL.
*/// cast to (struct section[_64] *)
void * macho_find_section_numbered(
constvoid * file_start,
constvoid * file_end,
uint8_t sect_num);
/*!
* @typedef macho_lc_callback
* @abstract The callback function used when scanning Mach-O load commands
* with macho_scan_load_commands.
* @discussion macho_lc_callback defines the callback function
* invoked by macho_scan_load_commands for each load command it encounters.
* The scan function passes a pointer to a user data struct that you can use
* for search parameters, running information, and search results.
* @param load_command A pointer to the Mach-O load command being processed.
* @param file_end A pointer to the end of the mapped Mach-O file,
* to be used for bounds checking.
* @param swap A boolean flag indicating whether the Mach-O file's byte order
* is opposite the host's.
* If nonzero, the callback needs to swap all multibyte values
* read from the Mach-O file.
* @param user_data A pointer to user-defined data that is passed unaltered
* across invocations of the callback function.
* @result Returns macho_seek_result_found if the requested item is found,
* macho_seek_result_not_found if is not found on this call,
* macho_seek_result_stop if the function determined that it does not exist,
* or macho_seek_result_error if an error occurs
* (particularly if any data structure to be accessed
* would run past the end of the file).
*/typedefmacho_seek_result (*macho_lc_callback)(
struct load_command * load_command,
constvoid * file_end,
uint8_t swap,
void * user_data
);
/*!
* @function macho_find_source_version
* @abstract Finds a mapped Mach-O file's LC_SOURCE_VERSION.
* @discussion
* The macho_find_source_version function locates the source version
* load command of a Mach-O file.
* @param mach_header A pointer to the beginning of the mapped Mach-O file.
* @param file_end A pointer to the end of the mapped Mach-O file.
* @param version A pointer to a uint64_t variable into which to store the
* contents of the 'version' field of the LC_SOURCE_VERSION load
* command from the mach-o header.
* @result Returns macho_seek_result_found if the source version is found,
* macho_seek_result_not_found if a source version is not defined in the
* given file, or macho_seek_result_error if an error occurs.
*/
macho_seek_result macho_find_source_version(
constvoid * file_start,
constvoid * file_end,
uint64_t * version);
/*!
* @function macho_scan_load_commands
* @abstract Iterates over the load commands of a Mach-O file using a callback.
* @discussion
* The macho_scan_load_commands iterates over the load commands within a
* Mach-O file, invoking a user-supplied callback until that callback
* returns a result indicating the scan should stop.
* @param mach_header A pointer to the beginning of the mapped Mach-O file.
* @param file_end A pointer to the end of the mapped Mach-O file.
* @param lc_callback A function that is invoked on each load command
* of the Mach-O file until the callback function
* indicates the scan is finished.
* @param user_data A pointer to user-defined data that is passed unaltered
* across invocations of the callback function.
* @result Returns a pointer to the requested section struct if it exists;
* otherwise returns NULL.
*/
macho_seek_result macho_scan_load_commands(
constvoid * file_start,
constvoid * file_end,
macho_lc_callback lc_callback,
void * user_data);
boolean_t macho_swap(
u_char * file);
boolean_t macho_unswap(
u_char * file);
struct segment_command * macho_get_segment_by_name(
struct mach_header * mach_header,
constchar * segname);
struct segment_command_64 * macho_get_segment_by_name_64(
struct mach_header_64 * mach_header,
constchar * segname);
struct section * macho_get_section_by_name(
struct mach_header * mach_header,
constchar * segname,
constchar * sectname);
struct section_64 * macho_get_section_by_name_64(
struct mach_header_64 * mach_header,
constchar * segname,
constchar * sectname);
boolean_t macho_remove_linkedit(
u_char * macho,
u_long * linkedit_size);
boolean_t macho_trim_linkedit(
u_char *macho,
u_long *amount_trimmed);
#endif/* __MACHO_UTIL_H__ */