Commit 4f6b2b18 authored by Robert Sesek's avatar Robert Sesek Committed by Commit Bot

[Mac] Delete CFBundleBlocker and third_party/mach_override.

The CFBundleBlocker's functionality is largely replaced (albeit without
an explicit allow-list) by code signing with library-validation and the
hardened runtime. Those code signing options also prohibit the program
text modification that mach_override performs, so it can be deleted.

Bug: 850193
Change-Id: Ieec7bf98d27f03a47140ac8abcf5e910db2eb01f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1675912Reviewed-by: default avatarMark Mentovai <mark@chromium.org>
Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Reviewed-by: default avatarDirk Pranke <dpranke@chromium.org>
Commit-Queue: Robert Sesek <rsesek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#672268}
parent 3e0b5d4a
...@@ -494,7 +494,6 @@ check_targets = [ ...@@ -494,7 +494,6 @@ check_targets = [
"//third_party/logilab/*", "//third_party/logilab/*",
"//third_party/lss/*", "//third_party/lss/*",
"//third_party/lzma_sdk/*", "//third_party/lzma_sdk/*",
"//third_party/mach_override/*",
"//third_party/markdown/*", "//third_party/markdown/*",
"//third_party/markupsafe/*", "//third_party/markupsafe/*",
"//third_party/material_design_icons/*", "//third_party/material_design_icons/*",
......
...@@ -88,7 +88,6 @@ ...@@ -88,7 +88,6 @@
#include "chrome/browser/chrome_browser_application_mac.h" #include "chrome/browser/chrome_browser_application_mac.h"
#include "chrome/browser/mac/relauncher.h" #include "chrome/browser/mac/relauncher.h"
#include "chrome/browser/shell_integration.h" #include "chrome/browser/shell_integration.h"
#include "chrome/common/mac/cfbundle_blocker.h"
#include "components/crash/core/common/objc_zombie.h" #include "components/crash/core/common/objc_zombie.h"
#include "ui/base/l10n/l10n_util_mac.h" #include "ui/base/l10n/l10n_util_mac.h"
#endif #endif
...@@ -630,8 +629,6 @@ bool ChromeMainDelegate::BasicStartupComplete(int* exit_code) { ...@@ -630,8 +629,6 @@ bool ChromeMainDelegate::BasicStartupComplete(int* exit_code) {
// there have more impact. // there have more impact.
const bool is_browser = !command_line.HasSwitch(switches::kProcessType); const bool is_browser = !command_line.HasSwitch(switches::kProcessType);
ObjcEvilDoers::ZombieEnable(true, is_browser ? 10000 : 1000); ObjcEvilDoers::ZombieEnable(true, is_browser ? 10000 : 1000);
chrome::common::mac::EnableCFBundleBlocker();
#endif #endif
content::Profiling::ProcessStarted(); content::Profiling::ProcessStarted();
......
...@@ -143,8 +143,6 @@ static_library("common") { ...@@ -143,8 +143,6 @@ static_library("common") {
"logging_chrome.h", "logging_chrome.h",
"mac/app_shim_launch.h", "mac/app_shim_launch.h",
"mac/app_shim_param_traits.h", "mac/app_shim_param_traits.h",
"mac/cfbundle_blocker.h",
"mac/cfbundle_blocker.mm",
"mac/launchd.h", "mac/launchd.h",
"mac/launchd.mm", "mac/launchd.mm",
"mac/service_management.h", "mac/service_management.h",
...@@ -467,10 +465,7 @@ static_library("common") { ...@@ -467,10 +465,7 @@ static_library("common") {
} }
if (is_mac) { if (is_mac) {
public_deps += [ public_deps += [ "//third_party/google_toolbox_for_mac" ]
"//third_party/google_toolbox_for_mac",
"//third_party/mach_override",
]
libs = [ "ServiceManagement.framework" ] libs = [ "ServiceManagement.framework" ]
} }
......
include_rules = [ include_rules = [
"+third_party/google_toolbox_for_mac/src", "+third_party/google_toolbox_for_mac/src",
"+third_party/mach_override",
] ]
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_COMMON_MAC_CFBUNDLE_BLOCKER_H_
#define CHROME_COMMON_MAC_CFBUNDLE_BLOCKER_H_
#if defined(__OBJC__)
@class NSString;
#else
class NSString;
#endif
namespace chrome {
namespace common {
namespace mac {
// Arranges to block loading of some third-party plugin code that might try
// to inject itself into the process. Modules loaded by CFBundle are blocked
// if located within specific directories. Because NSBundle uses CFBundle
// behind the scenes, this also blocks modules loaded by NSBundle when located
// in those same specific directories.
//
// Blocked modules include input managers, contextual menu items, and
// scripting additions installed in per-user (~/Library), per-machine
// (/Library), or network (/Network/Library) locations. Modules installed in
// the operating system location (/System/Library) are never blocked.
//
// This mechanism does not prevent CFBundle (or NSBundle) objects from being
// created, but it does block them from loading modules into the process.
// Returns whether the blocking mechanism setup was successful.
bool EnableCFBundleBlocker();
} // namespace mac
} // namespace common
} // namespace chrome
#endif // CHROME_COMMON_MAC_CFBUNDLE_BLOCKER_H_
This diff is collapsed.
// Copyright (c) 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_COMMON_MAC_CFBUNDLE_BLOCKER_PRIVATE_H_
#define CHROME_COMMON_MAC_CFBUNDLE_BLOCKER_PRIVATE_H_
#include <CoreFoundation/CoreFoundation.h>
extern "C" {
// _CFBundleLoadExecutableAndReturnError is the internal implementation that
// results in a dylib being loaded via dlopen. Both CFBundleLoadExecutable and
// CFBundleLoadExecutableAndReturnError are funneled into this routine. Other
// CFBundle functions may also call directly into here, perhaps due to
// inlining their calls to CFBundleLoadExecutable.
//
// See CF-476.19/CFBundle.c (10.5.8), CF-550.43/CFBundle.c (10.6.8), and
// CF-635/Bundle.c (10.7.0) and the disassembly of the shipping object code.
//
// Because this is a private function not declared by
// <CoreFoundation/CoreFoundation.h>, provide a declaration here.
Boolean _CFBundleLoadExecutableAndReturnError(CFBundleRef bundle,
Boolean force_global,
CFErrorRef* error);
} // extern "C"
// These are internal declarations that are shared between the implementation
// and the unit tests only.
namespace chrome {
namespace common {
namespace mac {
// Returns true if |bundle_id| and |version| identify a bundle that is allowed
// to be loaded even when found in a blocked directory.
//
// Exposed only for testing. Do not call from outside the implementation.
bool IsBundleAllowed(NSString* bundle_id, NSString* version);
typedef Boolean (*_CFBundleLoadExecutableAndReturnError_Type)(CFBundleRef,
Boolean,
CFErrorRef*);
// A function pointer that allows calling the original intercepted
// implementation. The unit tests use it to restore back the functionality.
// It is NULL until the blocking (intercepting) starts.
extern _CFBundleLoadExecutableAndReturnError_Type
g_original_underscore_cfbundle_load_executable_and_return_error;
} // namespace mac
} // namespace common
} // namespace chrome
#endif // CHROME_COMMON_MAC_CFBUNDLE_BLOCKER_PRIVATE_H_
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/common/mac/cfbundle_blocker.h"
#include "chrome/common/mac/cfbundle_blocker_private.h"
#import <Foundation/Foundation.h>
#include <stddef.h>
#include "base/stl_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/mach_override/mach_override.h"
namespace chrome {
namespace common {
namespace mac {
namespace {
struct IsBundleAllowedTestcase {
NSString* bundle_id;
NSString* version;
bool allowed;
};
TEST(CFBundleBlockerTest, IsBundleAllowed) {
const IsBundleAllowedTestcase kTestcases[] = {
// Block things without a bundle ID.
{ nil, nil, false },
// Block bundle IDs that aren't in the whitelist.
{ @"org.chromium.Chromium.evil", nil, false },
// The AllowedBundle structure for Google Authetnicator BT doesn't
// require a version, so this should work equally well with any version
// including no version at all.
{ @"com.google.osax.Google_Authenticator_BT", nil, true },
{ @"com.google.osax.Google_Authenticator_BT", @"0.5.0.0", true },
// Typos should be blocked.
{ @"com.google.osax.Google_Authenticator_B", nil, false },
{ @"com.google.osax.Google_Authenticator_BQ", nil, false },
{ @"com.google.osax.Google_Authenticator_BTQ", nil, false },
{ @"com.google.osax", nil, false },
{ @"com.google", nil, false },
{ @"com", nil, false },
{ @"", nil, false },
// MySpeed requires a version, so make sure that versions below don't work
// and versions above do.
{ @"com.enounce.MySpeed.osax", nil, false },
{ @"com.enounce.MySpeed.osax", @"", false },
{ @"com.enounce.MySpeed.osax", @"1200", false },
{ @"com.enounce.MySpeed.osax", @"1201", true },
{ @"com.enounce.MySpeed.osax", @"1202", true },
// DefaultFolderX is whitelisted as com.stclairsoft.DefaultFolderX. Make
// sure that "child" IDs such as com.stclairsoft.DefaultFolderX.osax work.
// It uses a dotted versioning scheme, so test the version comparator out.
{ @"com.stclairsoft.DefaultFolderX.osax", nil, false },
{ @"com.stclairsoft.DefaultFolderX.osax", @"", false },
{ @"com.stclairsoft.DefaultFolderX.osax", @"3.5.4", false },
{ @"com.stclairsoft.DefaultFolderX.osax", @"4.3.4", false },
{ @"com.stclairsoft.DefaultFolderX.osax", @"4.4.2", false },
{ @"com.stclairsoft.DefaultFolderX.osax", @"4.4.3", true },
{ @"com.stclairsoft.DefaultFolderX.osax", @"4.4.4", true },
{ @"com.stclairsoft.DefaultFolderX.osax", @"4.4.10", true },
{ @"com.stclairsoft.DefaultFolderX.osax", @"4.5", true },
{ @"com.stclairsoft.DefaultFolderX.osax", @"4.5.2", true },
{ @"com.stclairsoft.DefaultFolderX.osax", @"4.10", true },
{ @"com.stclairsoft.DefaultFolderX.osax", @"4.10.2", true },
{ @"com.stclairsoft.DefaultFolderX.osax", @"5", true },
{ @"com.stclairsoft.DefaultFolderX.osax", @"5.3", true },
{ @"com.stclairsoft.DefaultFolderX.osax", @"5.3.2", true },
// Other "child" IDs that might want to load.
{ @"com.stclairsoft.DefaultFolderX.CarbonPatcher", @"4.4.3", true },
{ @"com.stclairsoft.DefaultFolderX.CocoaPatcher", @"4.4.3", true },
};
for (size_t index = 0; index < base::size(kTestcases); ++index) {
const IsBundleAllowedTestcase& testcase = kTestcases[index];
NSString* bundle_id = testcase.bundle_id;
NSString* version = testcase.version;
NSString* version_print = version ? version : @"(nil)";
EXPECT_EQ(testcase.allowed, IsBundleAllowed(bundle_id, version))
<< "index " << index
<< ", bundle_id " << [bundle_id UTF8String]
<< ", version " << [version_print UTF8String];
}
}
TEST(CFBundleBlockerTest, EnableCFBundleBlocker_AllocationAttempts) {
static uint64_t s_num_test_calls = 0;
++s_num_test_calls;
if (g_original_underscore_cfbundle_load_executable_and_return_error) {
// The override has already happened. Overriding twice may lead to a hang
// so we need to restore it first.
mach_error_t err = mach_override_ptr(
reinterpret_cast<void*>(_CFBundleLoadExecutableAndReturnError),
reinterpret_cast<void*>(
g_original_underscore_cfbundle_load_executable_and_return_error),
nullptr);
ASSERT_EQ(err_none, err)
<< "Failed to restore CFBundleLoadExecutableAndReturnError";
}
uint64_t allocations_num_start = mach_override_ptr_allocation_attempts();
EXPECT_TRUE(EnableCFBundleBlocker());
// Note that each time mach_override_ptr is called to override the same
// function address. Each will allocate a page that will be attempted
// in the next call. So if this test is called in the same process multiple
// times, mach_override_ptr will end up attempting to allocate the same
// addresses over and over. Hence the 2 * s_num_test_calls added.
ASSERT_LE(mach_override_ptr_allocation_attempts(),
100UL + allocations_num_start + 2 * s_num_test_calls)
<< "Too many allocation attempts. "
"See https://bugs.chromium.org/p/chromium/issues/detail?id=730918";
}
} // namespace
} // namespace mac
} // namespace common
} // namespace chrome
...@@ -3133,7 +3133,6 @@ test("unit_tests") { ...@@ -3133,7 +3133,6 @@ test("unit_tests") {
"../common/crash_keys_unittest.cc", "../common/crash_keys_unittest.cc",
"../common/heap_profiler_controller_unittest.cc", "../common/heap_profiler_controller_unittest.cc",
"../common/ini_parser_unittest.cc", "../common/ini_parser_unittest.cc",
"../common/mac/cfbundle_blocker_unittest.mm",
"../common/mac/mock_launchd.h", "../common/mac/mock_launchd.h",
"../common/mac/mock_launchd.mm", "../common/mac/mock_launchd.mm",
"../common/mac/staging_watcher_unittest.mm", "../common/mac/staging_watcher_unittest.mm",
......
# Copyright (c) 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
assert(is_mac || is_ios)
config("libudis86_warnings") {
cflags = [
# syn.c contains a switch with an assert(false) in a default:
# block. In release builds, the function is missing a return.
"-Wno-return-type",
# Fires once in decode.c.
"-Wno-sometimes-uninitialized",
]
}
static_library("libudis86") {
sources = [
"libudis86/decode.c",
"libudis86/decode.h",
"libudis86/extern.h",
"libudis86/input.c",
"libudis86/input.h",
"libudis86/itab.c",
"libudis86/itab.h",
"libudis86/syn-att.c",
"libudis86/syn-intel.c",
"libudis86/syn.c",
"libudis86/syn.h",
"libudis86/types.h",
"libudis86/udint.h",
"libudis86/udis86.c",
"udis86.h",
]
defines = [
"HAVE_ASSERT_H",
"HAVE_STRING_H",
]
configs -= [
"//build/config/compiler:chromium_code",
# For UD_ASSERT(!"message");
"//build/config/clang:extra_warnings",
]
configs += [
"//build/config/compiler:no_chromium_code",
# Must be after no_chromium_code for warning flags to be ordered correctly.
":libudis86_warnings",
]
}
static_library("mach_override") {
sources = [
"mach_override.c",
"mach_override.h",
]
deps = [
":libudis86",
]
}
Copyright (c) 2003-2012 Jonathan 'Wolf' Rentzsch: http://rentzsch.com
Some rights reserved: http://opensource.org/licenses/mit
mach_override includes a copy of libudis86, licensed as follows:
Copyright (c) 2002-2009 Vivek Thampi
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
avi@chromium.org
mark@chromium.org
rsesek@chromium.org
Name: mach_override
Short Name: mach_override
Version: unknown
URL: https://github.com/rentzsch/mach_override
Date: 2014-05-11
Revision: 919148f94db54fc04d287eb6a42c0c36b166bbfa
License: MIT and 2-clause BSD
Security Critical: Yes
Description:
This package is used to replace framework functions with different
implementations at run time.
mach_override includes a copy of libudis86 1.7.1, available separately from
http://udis86.sourceforge.net/ and https://github.com/vmt/udis86 .
Local Modifications: Sped up allocation of branch island memory via usage of
vm_region to skip already allocated pages; add diagnostics for allocation
attempts. Catch allocation attempts on restricted pages.
diff --git a/third_party/mach_override/mach_override.c b/third_party/mach_override/mach_override.c
index 85a75e5c2067..ca68c0e90e61 100644
--- a/third_party/mach_override/mach_override.c
+++ b/third_party/mach_override/mach_override.c
@@ -8,6 +8,7 @@
#include "udis86.h"
#endif
+#include <libkern/OSAtomic.h>
#include <mach-o/dyld.h>
#include <mach/mach_init.h>
#include <mach/vm_map.h>
@@ -41,7 +42,7 @@ long kIslandTemplate[] = {
#define kInstructionHi 10
#define kInstructionLo 11
-#elif defined(__i386__)
+#elif defined(__i386__)
#define kOriginalInstructionsSize 16
@@ -61,6 +62,7 @@ char kIslandTemplate[] = {
#define kOriginalInstructionsSize 32
#define kJumpAddress kOriginalInstructionsSize + 6
+#define kMaxJumpOffset (0x7fffffffUL)
char kIslandTemplate[] = {
// kOriginalInstructionsSize nop instructions so that we
@@ -93,6 +95,14 @@ typedef struct {
int allocatedHigh;
} BranchIsland;
+/**************************
+*
+* Statistics
+*
+**************************/
+static volatile int64_t __attribute__((__aligned__((sizeof(int64_t)))))
+ g_mach_override_allocation_attempts = 0;
+
/**************************
*
* Funky Protos
@@ -101,6 +111,10 @@ typedef struct {
#pragma mark -
#pragma mark (Funky Protos)
+u_int64_t mach_override_ptr_allocation_attempts() {
+ return OSAtomicAdd64(0, &g_mach_override_allocation_attempts);
+}
+
mach_error_t
allocateBranchIsland(
BranchIsland **island,
@@ -267,7 +281,13 @@ mach_override_ptr(
#if defined(__i386__) || defined(__x86_64__)
if (!err) {
- uint32_t addressOffset = ((char*)escapeIsland - (char*)originalFunctionPtr - 5);
+ // TODO: On 64-bit, move to opcode FF/4 (jmp 64-bit absolute indirect)
+ // instead of E9 (jmp 32-bit relative to RIP). Then we should update
+ // allocateBranchIsland to simply allocate any page in the address space.
+ // See the 64-bit version of kIslandTemplate array.
+ int64_t addressOffset64 = ((char*)escapeIsland - (char*)originalFunctionPtr - 5);
+ int32_t addressOffset = addressOffset64;
+ assert(addressOffset64 == addressOffset);
addressOffset = OSSwapInt32(addressOffset);
jumpRelativeInstruction |= 0xE900000000000000LL;
@@ -385,13 +405,14 @@ allocateBranchIsland(
void *originalFunctionAddress)
{
assert( island );
-
+
mach_error_t err = err_none;
if( allocateHigh ) {
assert( sizeof( BranchIsland ) <= PAGE_SIZE );
vm_address_t page = 0;
#if defined(__i386__)
+ OSAtomicAdd64(1, &g_mach_override_allocation_attempts);
err = vm_allocate( mach_task_self(), &page, PAGE_SIZE, VM_FLAGS_ANYWHERE );
if( err == err_none )
*island = (BranchIsland*) page;
@@ -401,23 +422,42 @@ allocateBranchIsland(
vm_address_t first = 0xfeffffff;
vm_address_t last = 0xfe000000 + PAGE_SIZE;
#elif defined(__x86_64__)
- // 64-bit ASLR is in bits 13-28
- vm_address_t first = ((uint64_t)originalFunctionAddress & ~( (0xFUL << 28) | (PAGE_SIZE - 1) ) ) | (0x1UL << 31);
- vm_address_t last = (uint64_t)originalFunctionAddress & ~((0x1UL << 32) - 1);
+ // This logic is more complex due to the 32-bit limit of the jump out
+ // of the original function. Once that limitation is removed, we can
+ // use vm_allocate with VM_FLAGS_ANYWHERE as in the i386 code above.
+ const uint64_t kPageMask = ~(PAGE_SIZE - 1);
+ vm_address_t first = (uint64_t)originalFunctionAddress - kMaxJumpOffset;
+ first = (first & kPageMask) + PAGE_SIZE; // Align up to the next page start
+ if (first > (uint64_t)originalFunctionAddress) first = 0;
+ vm_address_t last = (uint64_t)originalFunctionAddress + kMaxJumpOffset;
+ if (last < (uint64_t)originalFunctionAddress) last = ULONG_MAX;
#endif
page = first;
int allocated = 0;
vm_map_t task_self = mach_task_self();
- while( !err && !allocated && page != last ) {
+ while( !err && !allocated && page < last ) {
+ OSAtomicAdd64(1, &g_mach_override_allocation_attempts);
err = vm_allocate( task_self, &page, PAGE_SIZE, 0 );
if( err == err_none )
allocated = 1;
- else if( err == KERN_NO_SPACE ) {
+ else if( err == KERN_NO_SPACE || err == KERN_INVALID_ADDRESS) {
#if defined(__x86_64__)
- page -= PAGE_SIZE;
+ // This memory region is not suitable, skip it:
+ vm_size_t region_size;
+ mach_msg_type_number_t int_count = VM_REGION_BASIC_INFO_COUNT_64;
+ vm_region_basic_info_data_64_t vm_region_info;
+ mach_port_t object_name;
+ // The call will move 'page' to the beginning of the region:
+ err = vm_region_64(task_self, &page, &region_size,
+ VM_REGION_BASIC_INFO_64, (vm_region_info_t)&vm_region_info,
+ &int_count, &object_name);
+ if (err == KERN_SUCCESS)
+ page += region_size;
+ else
+ break;
#else
page += PAGE_SIZE;
#endif
@@ -430,6 +470,7 @@ allocateBranchIsland(
err = KERN_NO_SPACE;
#endif
} else {
+ OSAtomicAdd64(1, &g_mach_override_allocation_attempts);
void *block = malloc( sizeof( BranchIsland ) );
if( block )
*island = block;
@@ -438,7 +479,7 @@ allocateBranchIsland(
}
if( !err )
(**island).allocatedHigh = allocateHigh;
-
+
return err;
}
diff --git a/third_party/mach_override/mach_override.h b/third_party/mach_override/mach_override.h
index ecd319c1cd7a..253f273d16b6 100644
--- a/third_party/mach_override/mach_override.h
+++ b/third_party/mach_override/mach_override.h
@@ -37,6 +37,18 @@ mach_override_ptr(
const void *overrideFunctionAddress,
void **originalFunctionReentryIsland );
+/****************************************************************************************
+ mach_override_ptr makes multiple allocation attempts with vm_allocate or malloc,
+ until a suitable address is found for the branch islands. This method returns the
+ global number of such attempts made by all mach_override_ptr calls so far. This
+ statistic is provided for testing purposes and it can be off, if mach_override_ptr
+ is called by multiple threads.
+
+ @result <- Total number of vm_allocate calls so far.
+
+ ************************************************************************************/
+u_int64_t mach_override_ptr_allocation_attempts();
+
__END_DECLS
/****************************************************************************************
This diff is collapsed.
/* udis86 - libudis86/decode.h
*
* Copyright (c) 2002-2009 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef UD_DECODE_H
#define UD_DECODE_H
#include "types.h"
#include "itab.h"
#define MAX_INSN_LENGTH 15
/* itab prefix bits */
#define P_none ( 0 )
#define P_cast ( 1 << 0 )
#define P_CAST(n) ( ( n >> 0 ) & 1 )
#define P_rexb ( 1 << 1 )
#define P_REXB(n) ( ( n >> 1 ) & 1 )
#define P_inv64 ( 1 << 4 )
#define P_INV64(n) ( ( n >> 4 ) & 1 )
#define P_rexw ( 1 << 5 )
#define P_REXW(n) ( ( n >> 5 ) & 1 )
#define P_def64 ( 1 << 7 )
#define P_DEF64(n) ( ( n >> 7 ) & 1 )
#define P_rexr ( 1 << 8 )
#define P_REXR(n) ( ( n >> 8 ) & 1 )
#define P_oso ( 1 << 9 )
#define P_OSO(n) ( ( n >> 9 ) & 1 )
#define P_aso ( 1 << 10 )
#define P_ASO(n) ( ( n >> 10 ) & 1 )
#define P_rexx ( 1 << 11 )
#define P_REXX(n) ( ( n >> 11 ) & 1 )
#define P_ImpAddr ( 1 << 12 )
#define P_IMPADDR(n) ( ( n >> 12 ) & 1 )
#define P_seg ( 1 << 13 )
#define P_SEG(n) ( ( n >> 13 ) & 1 )
#define P_str ( 1 << 14 )
#define P_STR(n) ( ( n >> 14 ) & 1 )
#define P_strz ( 1 << 15 )
#define P_STR_ZF(n) ( ( n >> 15 ) & 1 )
/* operand type constants -- order is important! */
enum ud_operand_code {
OP_NONE,
OP_A, OP_E, OP_M, OP_G,
OP_I, OP_F,
OP_R0, OP_R1, OP_R2, OP_R3,
OP_R4, OP_R5, OP_R6, OP_R7,
OP_AL, OP_CL, OP_DL,
OP_AX, OP_CX, OP_DX,
OP_eAX, OP_eCX, OP_eDX,
OP_rAX, OP_rCX, OP_rDX,
OP_ES, OP_CS, OP_SS, OP_DS,
OP_FS, OP_GS,
OP_ST0, OP_ST1, OP_ST2, OP_ST3,
OP_ST4, OP_ST5, OP_ST6, OP_ST7,
OP_J, OP_S, OP_O,
OP_I1, OP_I3, OP_sI,
OP_V, OP_W, OP_Q, OP_P,
OP_U, OP_N, OP_MU,
OP_R, OP_C, OP_D,
OP_MR
} UD_ATTR_PACKED;
/* operand size constants */
enum ud_operand_size {
SZ_NA = 0,
SZ_Z = 1,
SZ_V = 2,
SZ_RDQ = 7,
/* the following values are used as is,
* and thus hard-coded. changing them
* will break internals
*/
SZ_B = 8,
SZ_W = 16,
SZ_D = 32,
SZ_Q = 64,
SZ_T = 80,
SZ_O = 128,
SZ_Y = 17,
/*
* complex size types, that encode sizes for operands
* of type MR (memory or register), for internal use
* only. Id space 256 and above.
*/
SZ_BD = (SZ_B << 8) | SZ_D,
SZ_BV = (SZ_B << 8) | SZ_V,
SZ_WD = (SZ_W << 8) | SZ_D,
SZ_WV = (SZ_W << 8) | SZ_V,
SZ_WY = (SZ_W << 8) | SZ_Y,
SZ_DY = (SZ_D << 8) | SZ_Y,
SZ_WO = (SZ_W << 8) | SZ_O,
SZ_DO = (SZ_D << 8) | SZ_O,
SZ_QO = (SZ_Q << 8) | SZ_O,
} UD_ATTR_PACKED;
/* resolve complex size type.
*/
static inline enum ud_operand_size
Mx_mem_size(enum ud_operand_size size)
{
return (size >> 8) & 0xff;
}
static inline enum ud_operand_size
Mx_reg_size(enum ud_operand_size size)
{
return size & 0xff;
}
/* A single operand of an entry in the instruction table.
* (internal use only)
*/
struct ud_itab_entry_operand
{
enum ud_operand_code type;
enum ud_operand_size size;
};
/* A single entry in an instruction table.
*(internal use only)
*/
struct ud_itab_entry
{
enum ud_mnemonic_code mnemonic;
struct ud_itab_entry_operand operand1;
struct ud_itab_entry_operand operand2;
struct ud_itab_entry_operand operand3;
uint32_t prefix;
};
struct ud_lookup_table_list_entry {
const uint16_t *table;
enum ud_table_type type;
const char *meta;
};
static inline int
ud_opcode_field_sext(uint8_t primary_opcode)
{
return (primary_opcode & 0x02) != 0;
}
extern struct ud_itab_entry ud_itab[];
extern struct ud_lookup_table_list_entry ud_lookup_table_list[];
#endif /* UD_DECODE_H */
/* vim:cindent
* vim:expandtab
* vim:ts=4
* vim:sw=4
*/
/* udis86 - libudis86/extern.h
*
* Copyright (c) 2002-2009, 2013 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef UD_EXTERN_H
#define UD_EXTERN_H
#ifdef __cplusplus
extern "C" {
#endif
#include "types.h"
/* ============================= PUBLIC API ================================= */
extern void ud_init(struct ud*);
extern void ud_set_mode(struct ud*, uint8_t);
extern void ud_set_pc(struct ud*, uint64_t);
extern void ud_set_input_hook(struct ud*, int (*)(struct ud*));
extern void ud_set_input_buffer(struct ud*, const uint8_t*, size_t);
#ifndef __UD_STANDALONE__
extern void ud_set_input_file(struct ud*, FILE*);
#endif /* __UD_STANDALONE__ */
extern void ud_set_vendor(struct ud*, unsigned);
extern void ud_set_syntax(struct ud*, void (*)(struct ud*));
extern void ud_input_skip(struct ud*, size_t);
extern int ud_input_end(const struct ud*);
extern unsigned int ud_decode(struct ud*);
extern unsigned int ud_disassemble(struct ud*);
extern void ud_translate_intel(struct ud*);
extern void ud_translate_att(struct ud*);
extern const char* ud_insn_asm(const struct ud* u);
extern const uint8_t* ud_insn_ptr(const struct ud* u);
extern uint64_t ud_insn_off(const struct ud*);
extern const char* ud_insn_hex(struct ud*);
extern unsigned int ud_insn_len(const struct ud* u);
extern const struct ud_operand* ud_insn_opr(const struct ud *u, unsigned int n);
extern int ud_opr_is_sreg(const struct ud_operand *opr);
extern int ud_opr_isgpr(const struct ud_operand *opr);
extern const char* ud_lookup_mnemonic(enum ud_mnemonic_code c);
extern void ud_set_user_opaque_data(struct ud*, void*);
extern void* ud_get_user_opaque_data(const struct ud*);
extern uint64_t ud_insn_sext_imm(const struct ud*, const struct ud_operand*);
extern void ud_set_asm_buffer(struct ud *u, char *buf, size_t size);
extern void ud_set_sym_resolver(struct ud *u,
const char* (*resolver)(struct ud*,
uint64_t addr,
int64_t *offset));
/* ========================================================================== */
#ifdef __cplusplus
}
#endif
#endif /* UD_EXTERN_H */
/* udis86 - libudis86/input.c
*
* Copyright (c) 2002-2009 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "extern.h"
#include "types.h"
#include "input.h"
#include "udint.h"
/*
* inp_init
* Initializes the input system.
*/
static void
inp_init(struct ud *u)
{
u->inp_curr = 0;
u->inp_fill = 0;
u->inp_ctr = 0;
u->inp_end = 0;
}
/* -----------------------------------------------------------------------------
* inp_buff_hook() - Hook for buffered inputs.
* -----------------------------------------------------------------------------
*/
static int
inp_buff_hook(struct ud* u)
{
if (u->inp_buff < u->inp_buff_end)
return *u->inp_buff++;
else return -1;
}
#ifndef __UD_STANDALONE__
/* -----------------------------------------------------------------------------
* inp_file_hook() - Hook for FILE inputs.
* -----------------------------------------------------------------------------
*/
static int
inp_file_hook(struct ud* u)
{
return fgetc(u->inp_file);
}
#endif /* __UD_STANDALONE__*/
/* =============================================================================
* ud_inp_set_hook() - Sets input hook.
* =============================================================================
*/
void
ud_set_input_hook(register struct ud* u, int (*hook)(struct ud*))
{
u->inp_hook = hook;
inp_init(u);
}
/* =============================================================================
* ud_inp_set_buffer() - Set buffer as input.
* =============================================================================
*/
void
ud_set_input_buffer(register struct ud* u, const uint8_t* buf, size_t len)
{
u->inp_hook = inp_buff_hook;
u->inp_buff = buf;
u->inp_buff_end = buf + len;
inp_init(u);
}
#ifndef __UD_STANDALONE__
/* =============================================================================
* ud_input_set_file() - Set buffer as input.
* =============================================================================
*/
void
ud_set_input_file(register struct ud* u, FILE* f)
{
u->inp_hook = inp_file_hook;
u->inp_file = f;
inp_init(u);
}
#endif /* __UD_STANDALONE__ */
/* =============================================================================
* ud_input_skip() - Skip n input bytes.
* =============================================================================
*/
void
ud_input_skip(struct ud* u, size_t n)
{
while (n--) {
u->inp_hook(u);
}
}
/* =============================================================================
* ud_input_end() - Test for end of input.
* =============================================================================
*/
int
ud_input_end(const struct ud* u)
{
return (u->inp_curr == u->inp_fill) && u->inp_end;
}
/*
* ud_inp_next
* Loads and returns the next byte from input.
*
* inp_curr and inp_fill are pointers to the cache. The program is
* written based on the property that they are 8-bits in size, and
* will eventually wrap around forming a circular buffer. So, the
* size of the cache is 256 in size, kind of unnecessary yet
* optimal.
*
* A buffer inp_sess stores the bytes disassembled for a single
* session.
*/
uint8_t
ud_inp_next(struct ud* u)
{
int c = -1;
/* if current pointer is not upto the fill point in the
* input cache.
*/
if (u->inp_curr != u->inp_fill) {
c = u->inp_cache[ ++u->inp_curr ];
/* if !end-of-input, call the input hook and get a byte */
} else if (u->inp_end || (c = u->inp_hook(u)) == -1) {
/* end-of-input, mark it as an error, since the decoder,
* expected a byte more.
*/
UDERR(u, "byte expected, eoi received");
/* flag end of input */
u->inp_end = 1;
return 0;
} else {
/* increment pointers, we have a new byte. */
u->inp_curr = ++u->inp_fill;
/* add the byte to the cache */
u->inp_cache[u->inp_fill] = c;
}
/* record bytes input per decode-session. */
u->inp_sess[u->inp_ctr++] = c;
/* return byte */
return (uint8_t) c;
}
/*
vim: set ts=2 sw=2 expandtab
*/
/* udis86 - libudis86/input.h
*
* Copyright (c) 2002-2009 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef UD_INPUT_H
#define UD_INPUT_H
#include "types.h"
#include "udint.h"
uint8_t ud_inp_next(struct ud* u);
/*
* inp_start
* Should be called before each de-code operation.
*/
static inline void
inp_start(struct ud *u)
{
u->inp_ctr = 0;
}
/* inp_reset
* Resets the current pointer to its position before the current
* instruction disassembly was started.
*/
static inline void
inp_reset(struct ud *u)
{
u->inp_curr -= u->inp_ctr;
u->inp_ctr = 0;
}
/* inp_sess
* Returns the pointer to current session.
*/
static inline uint8_t*
inp_sess(struct ud *u)
{
return u->inp_sess;
}
/*
* inp_curr
* Returns the current input byte.
*/
static inline uint8_t
inp_curr(const struct ud *u)
{
return u->inp_cache[u->inp_curr];
}
/*
* inp_back
* Move back a single byte in the stream.
*/
static inline void
inp_back(struct ud* u)
{
if (u->inp_ctr > 0) {
--u->inp_curr;
--u->inp_ctr;
}
}
/*
* inp_peek
* Peek next byte in input.
*/
static inline uint8_t
inp_peek(struct ud* u)
{
uint8_t r = ud_inp_next(u);
if (!u->error) {
inp_back(u); /* Don't backup if there was an error */
}
return r;
}
/*
* inp_len
* Returns the number of bytes input in the current
* session.
*/
static inline size_t
inp_len(const struct ud *u)
{
return u->inp_ctr;
}
#endif /* UD_INPUT_H */
/*
vim: set ts=2 sw=2 expandtab
*/
This diff is collapsed.
This diff is collapsed.
/* udis86 - libudis86/syn-att.c
*
* Copyright (c) 2002-2009 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "types.h"
#include "extern.h"
#include "decode.h"
#include "itab.h"
#include "syn.h"
#include "udint.h"
/* -----------------------------------------------------------------------------
* opr_cast() - Prints an operand cast.
* -----------------------------------------------------------------------------
*/
static void
opr_cast(struct ud* u, struct ud_operand* op)
{
switch(op->size) {
case 16 : case 32 :
ud_asmprintf(u, "*"); break;
default: break;
}
}
/* -----------------------------------------------------------------------------
* gen_operand() - Generates assembly output for each operand.
* -----------------------------------------------------------------------------
*/
static void
gen_operand(struct ud* u, struct ud_operand* op)
{
switch(op->type) {
case UD_OP_CONST:
ud_asmprintf(u, "$0x%x", op->lval.udword);
break;
case UD_OP_REG:
ud_asmprintf(u, "%%%s", ud_reg_tab[op->base - UD_R_AL]);
break;
case UD_OP_MEM:
if (u->br_far) {
opr_cast(u, op);
}
if (u->pfx_seg) {
ud_asmprintf(u, "%%%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]);
}
if (op->offset != 0) {
ud_syn_print_mem_disp(u, op, 0);
}
if (op->base) {
ud_asmprintf(u, "(%%%s", ud_reg_tab[op->base - UD_R_AL]);
}
if (op->index) {
if (op->base) {
ud_asmprintf(u, ",");
} else {
ud_asmprintf(u, "(");
}
ud_asmprintf(u, "%%%s", ud_reg_tab[op->index - UD_R_AL]);
}
if (op->scale) {
ud_asmprintf(u, ",%d", op->scale);
}
if (op->base || op->index) {
ud_asmprintf(u, ")");
}
break;
case UD_OP_IMM:
ud_syn_print_imm(u, op);
break;
case UD_OP_JIMM:
ud_syn_print_addr(u, ud_syn_rel_target(u, op));
break;
case UD_OP_PTR:
switch (op->size) {
case 32:
ud_asmprintf(u, "$0x%x, $0x%x", op->lval.ptr.seg,
op->lval.ptr.off & 0xFFFF);
break;
case 48:
ud_asmprintf(u, "$0x%x, $0x%x", op->lval.ptr.seg,
op->lval.ptr.off);
break;
}
break;
default: return;
}
}
/* =============================================================================
* translates to AT&T syntax
* =============================================================================
*/
extern void
ud_translate_att(struct ud *u)
{
int size = 0;
int star = 0;
/* check if P_OSO prefix is used */
if (! P_OSO(u->itab_entry->prefix) && u->pfx_opr) {
switch (u->dis_mode) {
case 16:
ud_asmprintf(u, "o32 ");
break;
case 32:
case 64:
ud_asmprintf(u, "o16 ");
break;
}
}
/* check if P_ASO prefix was used */
if (! P_ASO(u->itab_entry->prefix) && u->pfx_adr) {
switch (u->dis_mode) {
case 16:
ud_asmprintf(u, "a32 ");
break;
case 32:
ud_asmprintf(u, "a16 ");
break;
case 64:
ud_asmprintf(u, "a32 ");
break;
}
}
if (u->pfx_lock)
ud_asmprintf(u, "lock ");
if (u->pfx_rep) {
ud_asmprintf(u, "rep ");
} else if (u->pfx_rep) {
ud_asmprintf(u, "repe ");
} else if (u->pfx_repne) {
ud_asmprintf(u, "repne ");
}
/* special instructions */
switch (u->mnemonic) {
case UD_Iretf:
ud_asmprintf(u, "lret ");
break;
case UD_Idb:
ud_asmprintf(u, ".byte 0x%x", u->operand[0].lval.ubyte);
return;
case UD_Ijmp:
case UD_Icall:
if (u->br_far) ud_asmprintf(u, "l");
if (u->operand[0].type == UD_OP_REG) {
star = 1;
}
ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic));
break;
case UD_Ibound:
case UD_Ienter:
if (u->operand[0].type != UD_NONE)
gen_operand(u, &u->operand[0]);
if (u->operand[1].type != UD_NONE) {
ud_asmprintf(u, ",");
gen_operand(u, &u->operand[1]);
}
return;
default:
ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic));
}
if (size == 8)
ud_asmprintf(u, "b");
else if (size == 16)
ud_asmprintf(u, "w");
else if (size == 64)
ud_asmprintf(u, "q");
if (star) {
ud_asmprintf(u, " *");
} else {
ud_asmprintf(u, " ");
}
if (u->operand[2].type != UD_NONE) {
gen_operand(u, &u->operand[2]);
ud_asmprintf(u, ", ");
}
if (u->operand[1].type != UD_NONE) {
gen_operand(u, &u->operand[1]);
ud_asmprintf(u, ", ");
}
if (u->operand[0].type != UD_NONE)
gen_operand(u, &u->operand[0]);
}
/*
vim: set ts=2 sw=2 expandtab
*/
/* udis86 - libudis86/syn-intel.c
*
* Copyright (c) 2002-2013 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "types.h"
#include "extern.h"
#include "decode.h"
#include "itab.h"
#include "syn.h"
#include "udint.h"
/* -----------------------------------------------------------------------------
* opr_cast() - Prints an operand cast.
* -----------------------------------------------------------------------------
*/
static void
opr_cast(struct ud* u, struct ud_operand* op)
{
if (u->br_far) {
ud_asmprintf(u, "far ");
}
switch(op->size) {
case 8: ud_asmprintf(u, "byte " ); break;
case 16: ud_asmprintf(u, "word " ); break;
case 32: ud_asmprintf(u, "dword "); break;
case 64: ud_asmprintf(u, "qword "); break;
case 80: ud_asmprintf(u, "tword "); break;
default: break;
}
}
/* -----------------------------------------------------------------------------
* gen_operand() - Generates assembly output for each operand.
* -----------------------------------------------------------------------------
*/
static void gen_operand(struct ud* u, struct ud_operand* op, int syn_cast)
{
switch(op->type) {
case UD_OP_REG:
ud_asmprintf(u, "%s", ud_reg_tab[op->base - UD_R_AL]);
break;
case UD_OP_MEM:
if (syn_cast) {
opr_cast(u, op);
}
ud_asmprintf(u, "[");
if (u->pfx_seg) {
ud_asmprintf(u, "%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]);
}
if (op->base) {
ud_asmprintf(u, "%s", ud_reg_tab[op->base - UD_R_AL]);
}
if (op->index) {
ud_asmprintf(u, "%s%s", op->base != UD_NONE? "+" : "",
ud_reg_tab[op->index - UD_R_AL]);
if (op->scale) {
ud_asmprintf(u, "*%d", op->scale);
}
}
if (op->offset != 0) {
ud_syn_print_mem_disp(u, op, (op->base != UD_NONE ||
op->index != UD_NONE) ? 1 : 0);
}
ud_asmprintf(u, "]");
break;
case UD_OP_IMM:
ud_syn_print_imm(u, op);
break;
case UD_OP_JIMM:
ud_syn_print_addr(u, ud_syn_rel_target(u, op));
break;
case UD_OP_PTR:
switch (op->size) {
case 32:
ud_asmprintf(u, "word 0x%x:0x%x", op->lval.ptr.seg,
op->lval.ptr.off & 0xFFFF);
break;
case 48:
ud_asmprintf(u, "dword 0x%x:0x%x", op->lval.ptr.seg,
op->lval.ptr.off);
break;
}
break;
case UD_OP_CONST:
if (syn_cast) opr_cast(u, op);
ud_asmprintf(u, "%d", op->lval.udword);
break;
default: return;
}
}
/* =============================================================================
* translates to intel syntax
* =============================================================================
*/
extern void
ud_translate_intel(struct ud* u)
{
/* check if P_OSO prefix is used */
if (!P_OSO(u->itab_entry->prefix) && u->pfx_opr) {
switch (u->dis_mode) {
case 16: ud_asmprintf(u, "o32 "); break;
case 32:
case 64: ud_asmprintf(u, "o16 "); break;
}
}
/* check if P_ASO prefix was used */
if (!P_ASO(u->itab_entry->prefix) && u->pfx_adr) {
switch (u->dis_mode) {
case 16: ud_asmprintf(u, "a32 "); break;
case 32: ud_asmprintf(u, "a16 "); break;
case 64: ud_asmprintf(u, "a32 "); break;
}
}
if (u->pfx_seg &&
u->operand[0].type != UD_OP_MEM &&
u->operand[1].type != UD_OP_MEM ) {
ud_asmprintf(u, "%s ", ud_reg_tab[u->pfx_seg - UD_R_AL]);
}
if (u->pfx_lock) {
ud_asmprintf(u, "lock ");
}
if (u->pfx_rep) {
ud_asmprintf(u, "rep ");
} else if (u->pfx_repe) {
ud_asmprintf(u, "repe ");
} else if (u->pfx_repne) {
ud_asmprintf(u, "repne ");
}
/* print the instruction mnemonic */
ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic));
if (u->operand[0].type != UD_NONE) {
int cast = 0;
ud_asmprintf(u, " ");
if (u->operand[0].type == UD_OP_MEM) {
if (u->operand[1].type == UD_OP_IMM ||
u->operand[1].type == UD_OP_CONST ||
u->operand[1].type == UD_NONE ||
(u->operand[0].size != u->operand[1].size &&
u->operand[1].type != UD_OP_REG)) {
cast = 1;
} else if (u->operand[1].type == UD_OP_REG &&
u->operand[1].base == UD_R_CL) {
switch (u->mnemonic) {
case UD_Ircl:
case UD_Irol:
case UD_Iror:
case UD_Ircr:
case UD_Ishl:
case UD_Ishr:
case UD_Isar:
cast = 1;
break;
default: break;
}
}
}
gen_operand(u, &u->operand[0], cast);
}
if (u->operand[1].type != UD_NONE) {
int cast = 0;
ud_asmprintf(u, ", ");
if (u->operand[1].type == UD_OP_MEM &&
u->operand[0].size != u->operand[1].size &&
!ud_opr_is_sreg(&u->operand[0])) {
cast = 1;
}
gen_operand(u, &u->operand[1], cast);
}
if (u->operand[2].type != UD_NONE) {
ud_asmprintf(u, ", ");
gen_operand(u, &u->operand[2], 0);
}
}
/*
vim: set ts=2 sw=2 expandtab
*/
/* udis86 - libudis86/syn.c
*
* Copyright (c) 2002-2013 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "types.h"
#include "decode.h"
#include "syn.h"
#include "udint.h"
/* -----------------------------------------------------------------------------
* Intel Register Table - Order Matters (types.h)!
* -----------------------------------------------------------------------------
*/
const char* ud_reg_tab[] =
{
"al", "cl", "dl", "bl",
"ah", "ch", "dh", "bh",
"spl", "bpl", "sil", "dil",
"r8b", "r9b", "r10b", "r11b",
"r12b", "r13b", "r14b", "r15b",
"ax", "cx", "dx", "bx",
"sp", "bp", "si", "di",
"r8w", "r9w", "r10w", "r11w",
"r12w", "r13w" , "r14w", "r15w",
"eax", "ecx", "edx", "ebx",
"esp", "ebp", "esi", "edi",
"r8d", "r9d", "r10d", "r11d",
"r12d", "r13d", "r14d", "r15d",
"rax", "rcx", "rdx", "rbx",
"rsp", "rbp", "rsi", "rdi",
"r8", "r9", "r10", "r11",
"r12", "r13", "r14", "r15",
"es", "cs", "ss", "ds",
"fs", "gs",
"cr0", "cr1", "cr2", "cr3",
"cr4", "cr5", "cr6", "cr7",
"cr8", "cr9", "cr10", "cr11",
"cr12", "cr13", "cr14", "cr15",
"dr0", "dr1", "dr2", "dr3",
"dr4", "dr5", "dr6", "dr7",
"dr8", "dr9", "dr10", "dr11",
"dr12", "dr13", "dr14", "dr15",
"mm0", "mm1", "mm2", "mm3",
"mm4", "mm5", "mm6", "mm7",
"st0", "st1", "st2", "st3",
"st4", "st5", "st6", "st7",
"xmm0", "xmm1", "xmm2", "xmm3",
"xmm4", "xmm5", "xmm6", "xmm7",
"xmm8", "xmm9", "xmm10", "xmm11",
"xmm12", "xmm13", "xmm14", "xmm15",
"rip"
};
uint64_t
ud_syn_rel_target(struct ud *u, struct ud_operand *opr)
{
const uint64_t trunc_mask = 0xffffffffffffffffull >> (64 - u->opr_mode);
switch (opr->size) {
case 8 : return (u->pc + opr->lval.sbyte) & trunc_mask;
case 16: return (u->pc + opr->lval.sword) & trunc_mask;
case 32: return (u->pc + opr->lval.sdword) & trunc_mask;
default: UD_ASSERT(!"invalid relative offset size.");
}
}
/*
* asmprintf
* Printf style function for printing translated assembly
* output. Returns the number of characters written and
* moves the buffer pointer forward. On an overflow,
* returns a negative number and truncates the output.
*/
int
ud_asmprintf(struct ud *u, char *fmt, ...)
{
int ret;
int avail;
va_list ap;
va_start(ap, fmt);
avail = u->asm_buf_size - u->asm_buf_fill - 1 /* nullchar */;
ret = vsnprintf((char*) u->asm_buf + u->asm_buf_fill, avail, fmt, ap);
if (ret < 0 || ret > avail) {
u->asm_buf_fill = u->asm_buf_size - 1;
} else {
u->asm_buf_fill += ret;
}
va_end(ap);
return ret;
}
void
ud_syn_print_addr(struct ud *u, uint64_t addr)
{
const char *name = NULL;
if (u->sym_resolver) {
int64_t offset = 0;
name = u->sym_resolver(u, addr, &offset);
if (name) {
if (offset) {
ud_asmprintf(u, "%s%+" FMT64 "d", name, offset);
} else {
ud_asmprintf(u, "%s", name);
}
return;
}
}
ud_asmprintf(u, "0x%" FMT64 "x", addr);
}
void
ud_syn_print_imm(struct ud* u, const struct ud_operand *op)
{
uint64_t v;
if (op->_oprcode == OP_sI && op->size != u->opr_mode) {
if (op->size == 8) {
v = (int64_t)op->lval.sbyte;
} else {
UD_ASSERT(op->size == 32);
v = (int64_t)op->lval.sdword;
}
if (u->opr_mode < 64) {
v = v & ((1ull << u->opr_mode) - 1ull);
}
} else {
switch (op->size) {
case 8 : v = op->lval.ubyte; break;
case 16: v = op->lval.uword; break;
case 32: v = op->lval.udword; break;
case 64: v = op->lval.uqword; break;
default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */
}
}
ud_asmprintf(u, "0x%" FMT64 "x", v);
}
void
ud_syn_print_mem_disp(struct ud* u, const struct ud_operand *op, int sign)
{
UD_ASSERT(op->offset != 0);
if (op->base == UD_NONE && op->index == UD_NONE) {
uint64_t v;
UD_ASSERT(op->scale == UD_NONE && op->offset != 8);
/* unsigned mem-offset */
switch (op->offset) {
case 16: v = op->lval.uword; break;
case 32: v = op->lval.udword; break;
case 64: v = op->lval.uqword; break;
default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */
}
ud_asmprintf(u, "0x%" FMT64 "x", v);
} else {
int64_t v;
UD_ASSERT(op->offset != 64);
switch (op->offset) {
case 8 : v = op->lval.sbyte; break;
case 16: v = op->lval.sword; break;
case 32: v = op->lval.sdword; break;
default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */
}
if (v < 0) {
ud_asmprintf(u, "-0x%" FMT64 "x", -v);
} else if (v > 0) {
ud_asmprintf(u, "%s0x%" FMT64 "x", sign? "+" : "", v);
}
}
}
/*
vim: set ts=2 sw=2 expandtab
*/
/* udis86 - libudis86/syn.h
*
* Copyright (c) 2002-2009
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef UD_SYN_H
#define UD_SYN_H
#include "types.h"
#ifndef __UD_STANDALONE__
# include <stdarg.h>
#endif /* __UD_STANDALONE__ */
extern const char* ud_reg_tab[];
uint64_t ud_syn_rel_target(struct ud*, struct ud_operand*);
#ifdef __GNUC__
int ud_asmprintf(struct ud *u, char *fmt, ...)
__attribute__ ((format (printf, 2, 3)));
#else
int ud_asmprintf(struct ud *u, char *fmt, ...);
#endif
void ud_syn_print_addr(struct ud *u, uint64_t addr);
void ud_syn_print_imm(struct ud* u, const struct ud_operand *op);
void ud_syn_print_mem_disp(struct ud* u, const struct ud_operand *, int sign);
#endif /* UD_SYN_H */
/*
vim: set ts=2 sw=2 expandtab
*/
/* udis86 - libudis86/types.h
*
* Copyright (c) 2002-2013 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef UD_TYPES_H
#define UD_TYPES_H
#ifdef __KERNEL__
/* -D__KERNEL__ is automatically passed on the command line when
building something as part of the Linux kernel */
# include <linux/kernel.h>
# include <linux/string.h>
# ifndef __UD_STANDALONE__
# define __UD_STANDALONE__ 1
#endif
#endif /* __KERNEL__ */
#if defined(_MSC_VER) || defined(__BORLANDC__)
# include <stdint.h>
# include <stdio.h>
# define inline __inline /* MS Visual Studio requires __inline
instead of inline for C code */
#elif !defined(__UD_STANDALONE__)
# include <stdio.h>
# include <inttypes.h>
#endif /* !__UD_STANDALONE__ */
/* gcc specific extensions */
#ifdef __GNUC__
# define UD_ATTR_PACKED __attribute__((packed))
#else
# define UD_ATTR_PACKED
#endif /* UD_ATTR_PACKED */
/* -----------------------------------------------------------------------------
* All possible "types" of objects in udis86. Order is Important!
* -----------------------------------------------------------------------------
*/
enum ud_type
{
UD_NONE,
/* 8 bit GPRs */
UD_R_AL, UD_R_CL, UD_R_DL, UD_R_BL,
UD_R_AH, UD_R_CH, UD_R_DH, UD_R_BH,
UD_R_SPL, UD_R_BPL, UD_R_SIL, UD_R_DIL,
UD_R_R8B, UD_R_R9B, UD_R_R10B, UD_R_R11B,
UD_R_R12B, UD_R_R13B, UD_R_R14B, UD_R_R15B,
/* 16 bit GPRs */
UD_R_AX, UD_R_CX, UD_R_DX, UD_R_BX,
UD_R_SP, UD_R_BP, UD_R_SI, UD_R_DI,
UD_R_R8W, UD_R_R9W, UD_R_R10W, UD_R_R11W,
UD_R_R12W, UD_R_R13W, UD_R_R14W, UD_R_R15W,
/* 32 bit GPRs */
UD_R_EAX, UD_R_ECX, UD_R_EDX, UD_R_EBX,
UD_R_ESP, UD_R_EBP, UD_R_ESI, UD_R_EDI,
UD_R_R8D, UD_R_R9D, UD_R_R10D, UD_R_R11D,
UD_R_R12D, UD_R_R13D, UD_R_R14D, UD_R_R15D,
/* 64 bit GPRs */
UD_R_RAX, UD_R_RCX, UD_R_RDX, UD_R_RBX,
UD_R_RSP, UD_R_RBP, UD_R_RSI, UD_R_RDI,
UD_R_R8, UD_R_R9, UD_R_R10, UD_R_R11,
UD_R_R12, UD_R_R13, UD_R_R14, UD_R_R15,
/* segment registers */
UD_R_ES, UD_R_CS, UD_R_SS, UD_R_DS,
UD_R_FS, UD_R_GS,
/* control registers*/
UD_R_CR0, UD_R_CR1, UD_R_CR2, UD_R_CR3,
UD_R_CR4, UD_R_CR5, UD_R_CR6, UD_R_CR7,
UD_R_CR8, UD_R_CR9, UD_R_CR10, UD_R_CR11,
UD_R_CR12, UD_R_CR13, UD_R_CR14, UD_R_CR15,
/* debug registers */
UD_R_DR0, UD_R_DR1, UD_R_DR2, UD_R_DR3,
UD_R_DR4, UD_R_DR5, UD_R_DR6, UD_R_DR7,
UD_R_DR8, UD_R_DR9, UD_R_DR10, UD_R_DR11,
UD_R_DR12, UD_R_DR13, UD_R_DR14, UD_R_DR15,
/* mmx registers */
UD_R_MM0, UD_R_MM1, UD_R_MM2, UD_R_MM3,
UD_R_MM4, UD_R_MM5, UD_R_MM6, UD_R_MM7,
/* x87 registers */
UD_R_ST0, UD_R_ST1, UD_R_ST2, UD_R_ST3,
UD_R_ST4, UD_R_ST5, UD_R_ST6, UD_R_ST7,
/* extended multimedia registers */
UD_R_XMM0, UD_R_XMM1, UD_R_XMM2, UD_R_XMM3,
UD_R_XMM4, UD_R_XMM5, UD_R_XMM6, UD_R_XMM7,
UD_R_XMM8, UD_R_XMM9, UD_R_XMM10, UD_R_XMM11,
UD_R_XMM12, UD_R_XMM13, UD_R_XMM14, UD_R_XMM15,
UD_R_RIP,
/* Operand Types */
UD_OP_REG, UD_OP_MEM, UD_OP_PTR, UD_OP_IMM,
UD_OP_JIMM, UD_OP_CONST
};
#include "itab.h"
union ud_lval {
int8_t sbyte;
uint8_t ubyte;
int16_t sword;
uint16_t uword;
int32_t sdword;
uint32_t udword;
int64_t sqword;
uint64_t uqword;
struct {
uint16_t seg;
uint32_t off;
} ptr;
};
/* -----------------------------------------------------------------------------
* struct ud_operand - Disassembled instruction Operand.
* -----------------------------------------------------------------------------
*/
struct ud_operand {
enum ud_type type;
uint8_t size;
enum ud_type base;
enum ud_type index;
uint8_t scale;
uint8_t offset;
union ud_lval lval;
uint64_t disp;
/*
* internal use only
*/
uint8_t _oprcode;
};
/* -----------------------------------------------------------------------------
* struct ud - The udis86 object.
* -----------------------------------------------------------------------------
*/
struct ud
{
/*
* input buffering
*/
int (*inp_hook) (struct ud*);
#ifndef __UD_STANDALONE__
FILE* inp_file;
#endif
uint8_t inp_curr;
uint8_t inp_fill;
uint8_t inp_ctr;
const uint8_t* inp_buff;
const uint8_t* inp_buff_end;
uint8_t inp_end;
uint8_t inp_cache[256];
uint8_t inp_sess[64];
void (*translator)(struct ud*);
uint64_t insn_offset;
char insn_hexcode[64];
/*
* Assembly output buffer
*/
char *asm_buf;
size_t asm_buf_size;
size_t asm_buf_fill;
char asm_buf_int[128];
/*
* Symbol resolver for use in the translation phase.
*/
const char* (*sym_resolver)(struct ud*, uint64_t addr, int64_t *offset);
uint8_t dis_mode;
uint64_t pc;
uint8_t vendor;
enum ud_mnemonic_code mnemonic;
struct ud_operand operand[3];
uint8_t error;
uint8_t pfx_rex;
uint8_t pfx_seg;
uint8_t pfx_opr;
uint8_t pfx_adr;
uint8_t pfx_lock;
uint8_t pfx_str;
uint8_t pfx_rep;
uint8_t pfx_repe;
uint8_t pfx_repne;
uint8_t default64;
uint8_t opr_mode;
uint8_t adr_mode;
uint8_t br_far;
uint8_t br_near;
uint8_t implicit_addr;
uint8_t have_modrm;
uint8_t modrm;
uint8_t primary_opcode;
void * user_opaque_data;
struct ud_itab_entry * itab_entry;
struct ud_lookup_table_list_entry *le;
};
/* -----------------------------------------------------------------------------
* Type-definitions
* -----------------------------------------------------------------------------
*/
typedef enum ud_type ud_type_t;
typedef enum ud_mnemonic_code ud_mnemonic_code_t;
typedef struct ud ud_t;
typedef struct ud_operand ud_operand_t;
#define UD_SYN_INTEL ud_translate_intel
#define UD_SYN_ATT ud_translate_att
#define UD_EOI (-1)
#define UD_INP_CACHE_SZ 32
#define UD_VENDOR_AMD 0
#define UD_VENDOR_INTEL 1
#define UD_VENDOR_ANY 2
#endif
/*
vim: set ts=2 sw=2 expandtab
*/
/* udis86 - libudis86/udint.h -- definitions for internal use only
*
* Copyright (c) 2002-2009 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _UDINT_H_
#define _UDINT_H_
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#ifdef HAVE_ASSERT_H
# include <assert.h>
# define UD_ASSERT(_x) assert(_x)
#else
# define UD_ASSERT(_x)
#endif /* !HAVE_ASSERT_H */
#ifdef LOGERR
#define UDERR(u, msg) \
do { \
(u)->error = 1; \
fprintf(stderr, "decode-error: %s:%d: %s", \
__FILE__, __LINE__, (msg)); \
} while (0)
#else
#define UDERR(u, m) \
do { \
(u)->error = 1; \
} while (0)
#endif /* !LOGERR */
#define UD_RETURN_ON_ERROR(u) \
do { \
if ((u)->error != 0) { \
return (u)->error; \
} \
} while (0)
#define UD_RETURN_WITH_ERROR(u, m) \
do { \
UDERR(u, m); \
return (u)->error; \
} while (0)
/* printf formatting int64 specifier */
#ifdef FMT64
# undef FMT64
#endif
#if defined(_MSC_VER) || defined(__BORLANDC__)
# define FMT64 "I64"
#else
# if defined(__APPLE__)
# define FMT64 "ll"
# elif defined(__amd64__) || defined(__x86_64__)
# define FMT64 "l"
# else
# define FMT64 "ll"
# endif /* !x64 */
#endif
#endif /* _UDINT_H_ */
/* udis86 - libudis86/udis86.c
*
* Copyright (c) 2002-2013 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "input.h"
#include "extern.h"
#include "decode.h"
#if !defined(__UD_STANDALONE__)
# if HAVE_STRING_H
# include <string.h>
# endif
#endif /* !__UD_STANDALONE__ */
/* =============================================================================
* ud_init() - Initializes ud_t object.
* =============================================================================
*/
extern void
ud_init(struct ud* u)
{
memset((void*)u, 0, sizeof(struct ud));
ud_set_mode(u, 16);
u->mnemonic = UD_Iinvalid;
ud_set_pc(u, 0);
#ifndef __UD_STANDALONE__
ud_set_input_file(u, stdin);
#endif /* __UD_STANDALONE__ */
ud_set_asm_buffer(u, u->asm_buf_int, sizeof(u->asm_buf_int));
}
/* =============================================================================
* ud_disassemble() - disassembles one instruction and returns the number of
* bytes disassembled. A zero means end of disassembly.
* =============================================================================
*/
extern unsigned int
ud_disassemble(struct ud* u)
{
if (ud_input_end(u))
return 0;
u->asm_buf[0] = 0;
if (ud_decode(u) == 0)
return 0;
if (u->translator)
u->translator(u);
return ud_insn_len(u);
}
/* =============================================================================
* ud_set_mode() - Set Disassemly Mode.
* =============================================================================
*/
extern void
ud_set_mode(struct ud* u, uint8_t m)
{
switch(m) {
case 16:
case 32:
case 64: u->dis_mode = m ; return;
default: u->dis_mode = 16; return;
}
}
/* =============================================================================
* ud_set_vendor() - Set vendor.
* =============================================================================
*/
extern void
ud_set_vendor(struct ud* u, unsigned v)
{
switch(v) {
case UD_VENDOR_INTEL:
u->vendor = v;
break;
case UD_VENDOR_ANY:
u->vendor = v;
break;
default:
u->vendor = UD_VENDOR_AMD;
}
}
/* =============================================================================
* ud_set_pc() - Sets code origin.
* =============================================================================
*/
extern void
ud_set_pc(struct ud* u, uint64_t o)
{
u->pc = o;
}
/* =============================================================================
* ud_set_syntax() - Sets the output syntax.
* =============================================================================
*/
extern void
ud_set_syntax(struct ud* u, void (*t)(struct ud*))
{
u->translator = t;
}
/* =============================================================================
* ud_insn() - returns the disassembled instruction
* =============================================================================
*/
const char*
ud_insn_asm(const struct ud* u)
{
return u->asm_buf;
}
/* =============================================================================
* ud_insn_offset() - Returns the offset.
* =============================================================================
*/
uint64_t
ud_insn_off(const struct ud* u)
{
return u->insn_offset;
}
/* =============================================================================
* ud_insn_hex() - Returns hex form of disassembled instruction.
* =============================================================================
*/
const char*
ud_insn_hex(struct ud* u)
{
u->insn_hexcode[0] = 0;
if (!u->error) {
unsigned int i;
unsigned char *src_ptr = inp_sess(u);
char* src_hex;
src_hex = (char*) u->insn_hexcode;
/* for each byte used to decode instruction */
for (i = 0; i < u->inp_ctr && i < sizeof(u->insn_hexcode) / 2;
++i, ++src_ptr) {
sprintf(src_hex, "%02x", *src_ptr & 0xFF);
src_hex += 2;
}
}
return u->insn_hexcode;
}
/* =============================================================================
* ud_insn_ptr() - Returns code disassembled.
* =============================================================================
*/
extern const uint8_t*
ud_insn_ptr(const struct ud* u)
{
return u->inp_sess;
}
/* =============================================================================
* ud_insn_len() - Returns the count of bytes disassembled.
* =============================================================================
*/
extern unsigned int
ud_insn_len(const struct ud* u)
{
return u->inp_ctr;
}
/* =============================================================================
* ud_insn_get_opr
* Return the operand struct representing the nth operand of
* the currently disassembled instruction. Returns NULL if
* there's no such operand.
* =============================================================================
*/
const struct ud_operand*
ud_insn_opr(const struct ud *u, unsigned int n)
{
if (n > 2 || u->operand[n].type == UD_NONE) {
return NULL;
} else {
return &u->operand[n];
}
}
/* =============================================================================
* ud_opr_is_sreg
* Returns non-zero if the given operand is of a segment register type.
* =============================================================================
*/
int
ud_opr_is_sreg(const struct ud_operand *opr)
{
return opr->type == UD_OP_REG &&
opr->base >= UD_R_ES &&
opr->base <= UD_R_GS;
}
/* =============================================================================
* ud_opr_is_sreg
* Returns non-zero if the given operand is of a general purpose
* register type.
* =============================================================================
*/
int
ud_opr_is_gpr(const struct ud_operand *opr)
{
return opr->type == UD_OP_REG &&
opr->base >= UD_R_AL &&
opr->base <= UD_R_R15;
}
/* =============================================================================
* ud_set_user_opaque_data
* ud_get_user_opaque_data
* Get/set user opaqute data pointer
* =============================================================================
*/
void
ud_set_user_opaque_data(struct ud * u, void* opaque)
{
u->user_opaque_data = opaque;
}
void*
ud_get_user_opaque_data(const struct ud *u)
{
return u->user_opaque_data;
}
/* =============================================================================
* ud_set_asm_buffer
* Allow the user to set an assembler output buffer. If `buf` is NULL,
* we switch back to the internal buffer.
* =============================================================================
*/
void
ud_set_asm_buffer(struct ud *u, char *buf, size_t size)
{
if (buf == NULL) {
ud_set_asm_buffer(u, u->asm_buf_int, sizeof(u->asm_buf_int));
} else {
u->asm_buf = buf;
u->asm_buf_size = size;
}
}
/* =============================================================================
* ud_set_sym_resolver
* Set symbol resolver for relative targets used in the translation
* phase.
*
* The resolver is a function that takes a uint64_t address and returns a
* symbolic name for the that address. The function also takes a second
* argument pointing to an integer that the client can optionally set to a
* non-zero value for offsetted targets. (symbol+offset) The function may
* also return NULL, in which case the translator only prints the target
* address.
*
* The function pointer maybe NULL which resets symbol resolution.
* =============================================================================
*/
void
ud_set_sym_resolver(struct ud *u, const char* (*resolver)(struct ud*,
uint64_t addr,
int64_t *offset))
{
u->sym_resolver = resolver;
}
/*
vim:set ts=2 sw=2 expandtab
*/
This diff is collapsed.
// mach_override.h semver:1.2.0
// Copyright (c) 2003-2012 Jonathan 'Wolf' Rentzsch: http://rentzsch.com
// Some rights reserved: http://opensource.org/licenses/mit
// https://github.com/rentzsch/mach_override
#ifndef _mach_override_
#define _mach_override_
#include <sys/types.h>
#include <mach/error.h>
#define err_cannot_override (err_local|1)
__BEGIN_DECLS
/****************************************************************************************
Dynamically overrides the function implementation referenced by
originalFunctionAddress with the implentation pointed to by overrideFunctionAddress.
Optionally returns a pointer to a "reentry island" which, if jumped to, will resume
the original implementation.
@param originalFunctionAddress -> Required address of the function to
override (with overrideFunctionAddress).
@param overrideFunctionAddress -> Required address to the overriding
function.
@param originalFunctionReentryIsland <- Optional pointer to pointer to the
reentry island. Can be NULL.
@result <- err_cannot_override if the original
function's implementation begins with
the 'mfctr' instruction.
************************************************************************************/
mach_error_t
mach_override_ptr(
void *originalFunctionAddress,
const void *overrideFunctionAddress,
void **originalFunctionReentryIsland );
/****************************************************************************************
mach_override_ptr makes multiple allocation attempts with vm_allocate or malloc,
until a suitable address is found for the branch islands. This method returns the
global number of such attempts made by all mach_override_ptr calls so far. This
statistic is provided for testing purposes and it can be off, if mach_override_ptr
is called by multiple threads.
@result <- Total number of vm_allocate calls so far.
************************************************************************************/
u_int64_t mach_override_ptr_allocation_attempts();
__END_DECLS
/****************************************************************************************
If you're using C++ this macro will ease the tedium of typedef'ing, naming, keeping
track of reentry islands and defining your override code. See test_mach_override.cp
for example usage.
************************************************************************************/
#ifdef __cplusplus
#define MACH_OVERRIDE( ORIGINAL_FUNCTION_RETURN_TYPE, ORIGINAL_FUNCTION_NAME, ORIGINAL_FUNCTION_ARGS, ERR ) \
{ \
static ORIGINAL_FUNCTION_RETURN_TYPE (*ORIGINAL_FUNCTION_NAME##_reenter)ORIGINAL_FUNCTION_ARGS; \
static bool ORIGINAL_FUNCTION_NAME##_overriden = false; \
class mach_override_class__##ORIGINAL_FUNCTION_NAME { \
public: \
static kern_return_t override(void *originalFunctionPtr) { \
kern_return_t result = err_none; \
if (!ORIGINAL_FUNCTION_NAME##_overriden) { \
ORIGINAL_FUNCTION_NAME##_overriden = true; \
result = mach_override_ptr( (void*)originalFunctionPtr, \
(void*)mach_override_class__##ORIGINAL_FUNCTION_NAME::replacement, \
(void**)&ORIGINAL_FUNCTION_NAME##_reenter ); \
} \
return result; \
} \
static ORIGINAL_FUNCTION_RETURN_TYPE replacement ORIGINAL_FUNCTION_ARGS {
#define END_MACH_OVERRIDE( ORIGINAL_FUNCTION_NAME ) \
} \
}; \
\
err = mach_override_class__##ORIGINAL_FUNCTION_NAME::override((void*)ORIGINAL_FUNCTION_NAME); \
}
#endif
#endif // _mach_override_
/* udis86 - udis86.h
*
* Copyright (c) 2002-2009 Vivek Thampi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef UDIS86_H
#define UDIS86_H
#include "third_party/mach_override/libudis86/types.h"
#include "third_party/mach_override/libudis86/extern.h"
#include "third_party/mach_override/libudis86/itab.h"
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment