disassemble.cc
Go to the documentation of this file.
1 // Copyright 2016 Google Inc. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <string>
16 
17 #include "absl/strings/ascii.h"
18 #include "absl/strings/escaping.h"
19 #include "absl/strings/str_cat.h"
20 #include "absl/strings/string_view.h"
21 #include "absl/strings/substitute.h"
22 #include "bloaty.h"
23 #include "capstone/capstone.h"
24 #include "re.h"
25 #include "util.h"
26 
27 using absl::string_view;
28 
29 namespace bloaty {
30 
31 namespace {
32 
33 static std::string RightPad(const std::string& input, size_t size) {
35  while (ret.size() < size) {
36  ret += " ";
37  }
38  return ret;
39 }
40 
41 } // anonymous namespace
42 
44  if (info.arch != CS_ARCH_X86) {
45  // x86 only for now.
46  return;
47  }
48 
49  csh handle;
50  if (cs_open(info.arch, info.mode, &handle) != CS_ERR_OK ||
52  THROW("Couldn't initialize Capstone");
53  }
54 
55  if (info.text.size() == 0) {
56  cs_close(&handle);
57  THROW("Tried to disassemble empty function.");
58  }
59 
60  cs_insn *in = cs_malloc(handle);
61  uint64_t address = info.start_address;
62  const uint8_t* ptr = reinterpret_cast<const uint8_t*>(info.text.data());
63  size_t size = info.text.size();
64 
65  while (size > 0) {
66  if (!cs_disasm_iter(handle, &ptr, &size, &address, in)) {
67  // Some symbols that end up in the .text section aren't really functions
68  // but data. Not sure why this happens.
69  if (verbose_level > 1) {
70  printf("Error disassembling function at address: %" PRIx64 "\n",
71  address);
72  }
73  goto cleanup;
74  }
75 
76  size_t count = in->detail->x86.op_count;
77  for (size_t i = 0; i < count; i++) {
78  cs_x86_op* op = &in->detail->x86.operands[i];
79  if (op->type == X86_OP_MEM && op->mem.base == X86_REG_RIP &&
80  op->mem.segment == X86_REG_INVALID &&
81  op->mem.index == X86_REG_INVALID) {
82  uint64_t to_address = in->address + in->size + op->mem.disp;
83  if (to_address) {
84  sink->AddVMRangeForVMAddr("x86_disassemble", in->address, to_address,
86  }
87  }
88  }
89  }
90 
91 cleanup:
92  cs_free(in, 1);
93  cs_close(&handle);
94 }
95 
97  switch (arch) {
98  case CS_ARCH_X86:
99  switch (in->id) {
100  case X86_INS_JAE:
101  case X86_INS_JA:
102  case X86_INS_JBE:
103  case X86_INS_JB:
104  case X86_INS_JCXZ:
105  case X86_INS_JECXZ:
106  case X86_INS_JE:
107  case X86_INS_JGE:
108  case X86_INS_JG:
109  case X86_INS_JLE:
110  case X86_INS_JL:
111  case X86_INS_JMP:
112  case X86_INS_JNE:
113  case X86_INS_JNO:
114  case X86_INS_JNP:
115  case X86_INS_JNS:
116  case X86_INS_JO:
117  case X86_INS_JP:
118  case X86_INS_JS:
119  case X86_INS_CALL: {
120  auto op0 = in->detail->x86.operands[0];
121  if (op0.type == X86_OP_IMM) {
122  *target = op0.imm;
123  return true;
124  }
125  return false;
126  }
127  default:
128  return false;
129  }
130  default:
131  return false;
132  }
133 }
134 
137 
138  csh handle;
139  if (cs_open(info.arch, info.mode, &handle) != CS_ERR_OK ||
141  THROW("Couldn't initialize Capstone");
142  }
143 
144  if (info.text.size() == 0) {
145  THROW("Tried to disassemble empty function.");
146  }
147 
148  cs_insn *insn;
149  size_t count =
150  cs_disasm(handle, reinterpret_cast<const uint8_t *>(info.text.data()),
151  info.text.size(), info.start_address, 0, &insn);
152 
153  if (count == 0) {
154  THROW("Error disassembling function.");
155  }
156 
157  std::map<uint64_t, int> local_labels;
158 
159  for (size_t i = 0; i < count; i++) {
160  cs_insn *in = insn + i;
162  if (TryGetJumpTarget(info.arch, in, &target) &&
163  target >= info.start_address &&
164  target < info.start_address + info.text.size()) {
165  local_labels[target] = 0; // Fill in real value later.
166  }
167  }
168 
169  int label = 0;
170  for (auto& pair : local_labels) {
171  pair.second = label++;
172  }
173 
174  for (size_t i = 0; i < count; i++) {
175  cs_insn *in = insn + i;
177  string_view(reinterpret_cast<const char*>(in->bytes), in->size));
178  string_view mnemonic(in->mnemonic);
179  std::string op_str(in->op_str);
182 
183  if (info.arch == CS_ARCH_X86) {
184  if (in->id == X86_INS_LEA) {
185  ReImpl::GlobalReplace(&op_str, "\\w?word ptr ", "");
186  } else if (in->id == X86_INS_NOP) {
187  op_str.clear();
188  } else {
189  // qword ptr => QWORD
190  while (ReImpl::PartialMatch(op_str, "(\\w?word) ptr", &match)) {
191  std::string upper_match = match;
192  absl::AsciiStrToUpper(&upper_match);
193  ReImpl::Replace(&op_str, match + " ptr", upper_match);
194  }
195  }
196  }
197 
198  ReImpl::GlobalReplace(&op_str, " ", "");
199 
200  auto iter = local_labels.find(in->address);
201  if (iter != local_labels.end()) {
202  label = std::to_string(iter->second) + ":";
203  }
204 
206  if (TryGetJumpTarget(info.arch, in, &target)) {
207  auto iter = local_labels.find(target);
209  if (iter != local_labels.end()) {
210  if (target > in->address) {
211  op_str = ">" + std::to_string(iter->second);
212  } else {
213  op_str = "<" + std::to_string(iter->second);
214  }
215  } else if (info.symbol_map.vm_map.TryGetLabel(target, &label)) {
216  op_str = label;
217  }
218  }
219 
220  absl::StrAppend(&ret, " ", RightPad(label, 4),
221  RightPad(std::string(mnemonic), 8), " ", op_str, "\n");
222  }
223 
224  cs_close(&handle);
225  return ret;
226 }
227 
228 } // namespace bloaty
ptr
char * ptr
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:45
cs_close
CAPSTONE_EXPORT cs_err CAPSTONE_API cs_close(csh *handle)
Definition: cs.c:522
bloaty
Definition: bloaty.cc:69
absl::StrAppend
void StrAppend(std::string *dest, const AlphaNum &a)
Definition: abseil-cpp/absl/strings/str_cat.cc:193
cleanup
void cleanup(void)
Definition: bloaty/third_party/zlib/examples/enough.c:182
bloaty::DisassemblyInfo::symbol_map
DualMap symbol_map
Definition: bloaty.h:319
X86_INS_JNO
@ X86_INS_JNO
Definition: x86.h:652
X86_INS_CALL
@ X86_INS_CALL
Definition: x86.h:442
bloaty::verbose_level
int verbose_level
Definition: bloaty.cc:74
bloaty::DualMap::vm_map
RangeMap vm_map
Definition: bloaty.h:313
match
unsigned char match[65280+2]
Definition: bloaty/third_party/zlib/examples/gun.c:165
cs_disasm
CAPSTONE_EXPORT size_t CAPSTONE_API cs_disasm(csh ud, const uint8_t *buffer, size_t size, uint64_t offset, size_t count, cs_insn **insn)
Definition: cs.c:822
X86_OP_IMM
@ X86_OP_IMM
= CS_OP_IMM (Immediate operand).
Definition: x86.h:161
X86_INS_JO
@ X86_INS_JO
Definition: x86.h:655
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
printf
_Use_decl_annotations_ int __cdecl printf(const char *_Format,...)
Definition: cs_driver.c:91
bloaty.h
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
X86_INS_JL
@ X86_INS_JL
Definition: x86.h:649
bloaty::DisassembleFunction
std::string DisassembleFunction(const DisassemblyInfo &info)
Definition: disassemble.cc:135
cs_open
CAPSTONE_EXPORT cs_err CAPSTONE_API cs_open(cs_arch arch, cs_mode mode, csh *handle)
Definition: cs.c:474
X86_INS_JB
@ X86_INS_JB
Definition: x86.h:642
cs_arch
cs_arch
Architecture type.
Definition: capstone.h:74
CS_OPT_DETAIL
@ CS_OPT_DETAIL
Break down instruction structure into details.
Definition: capstone.h:172
bloaty::DisassemblyInfo::mode
cs_mode mode
Definition: bloaty.h:321
bloaty::DisassemblyInfo::start_address
uint64_t start_address
Definition: bloaty.h:322
X86_INS_JNE
@ X86_INS_JNE
Definition: x86.h:651
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
X86_INS_JG
@ X86_INS_JG
Definition: x86.h:647
X86_INS_JP
@ X86_INS_JP
Definition: x86.h:656
cs_option
CAPSTONE_EXPORT cs_err CAPSTONE_API cs_option(csh ud, cs_opt_type type, size_t value)
Definition: cs.c:670
bloaty::DisassemblyInfo::arch
cs_arch arch
Definition: bloaty.h:320
capstone.h
in
const char * in
Definition: third_party/abseil-cpp/absl/strings/internal/str_format/parser_test.cc:391
capstone.CS_ERR_OK
CS_ERR_OK
Definition: third_party/bloaty/third_party/capstone/bindings/python/capstone/__init__.py:237
absl::BytesToHexString
std::string BytesToHexString(absl::string_view from)
Definition: abseil-cpp/absl/strings/escaping.cc:940
bloaty::RangeSink::kUnknownSize
static constexpr uint64_t kUnknownSize
Definition: bloaty.h:211
bloaty::ReImpl::Replace
static ABSL_ATTRIBUTE_NORETURN bool Replace(std::string *, const ReImpl &, std::string)
Definition: bloaty/src/re.h:83
gen_synthetic_protos.label
label
Definition: gen_synthetic_protos.py:102
absl::string_view::size
constexpr size_type size() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:277
absl::AsciiStrToUpper
void AsciiStrToUpper(std::string *s)
Definition: abseil-cpp/absl/strings/ascii.cc:164
X86_INS_NOP
@ X86_INS_NOP
Definition: x86.h:880
THROW
#define THROW(msg)
Definition: bloaty/src/util.h:45
X86_INS_JA
@ X86_INS_JA
Definition: x86.h:640
CS_ARCH_X86
@ CS_ARCH_X86
X86 architecture (including x86 & x86-64)
Definition: capstone.h:78
uint64_t
unsigned __int64 uint64_t
Definition: stdint-msvc2008.h:90
bloaty::ReImpl::PartialMatch
static ABSL_ATTRIBUTE_NORETURN bool PartialMatch(const std::string &, const ReImpl &, A &&...)
Definition: bloaty/src/re.h:74
X86_INS_JAE
@ X86_INS_JAE
Definition: x86.h:639
CS_OPT_ON
@ CS_OPT_ON
Turn ON an option (CS_OPT_DETAIL, CS_OPT_SKIPDATA).
Definition: capstone.h:184
bloaty::RangeSink
Definition: bloaty.h:110
X86_OP_MEM
@ X86_OP_MEM
= CS_OP_MEM (Memory operand).
Definition: x86.h:162
bloaty::TryGetJumpTarget
bool TryGetJumpTarget(cs_arch arch, cs_insn *in, uint64_t *target)
Definition: disassemble.cc:96
cs_x86_op
Instruction operand.
Definition: x86.h:275
X86_INS_JNS
@ X86_INS_JNS
Definition: x86.h:654
arch
cs_arch arch
Definition: cstool.c:13
X86_INS_JLE
@ X86_INS_JLE
Definition: x86.h:648
re.h
X86_INS_JMP
@ X86_INS_JMP
Definition: x86.h:650
bloaty::DisassemblyInfo::text
absl::string_view text
Definition: bloaty.h:318
X86_INS_JCXZ
@ X86_INS_JCXZ
Definition: x86.h:643
csh
size_t csh
Definition: capstone.h:71
X86_REG_INVALID
@ X86_REG_INVALID
Definition: x86.h:20
X86_INS_JS
@ X86_INS_JS
Definition: x86.h:658
cs_disasm_iter
CAPSTONE_EXPORT bool CAPSTONE_API cs_disasm_iter(csh ud, const uint8_t **code, size_t *size, uint64_t *address, cs_insn *insn)
Definition: cs.c:1080
bytes
uint8 bytes[10]
Definition: bloaty/third_party/protobuf/src/google/protobuf/io/coded_stream_unittest.cc:153
sink
FormatSinkImpl * sink
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:450
count
int * count
Definition: bloaty/third_party/googletest/googlemock/test/gmock_stress_test.cc:96
bloaty::DisassembleFindReferences
void DisassembleFindReferences(const DisassemblyInfo &info, RangeSink *sink)
Definition: disassemble.cc:43
ret
UniquePtr< SSL_SESSION > ret
Definition: ssl_x509.cc:1029
string_view
absl::string_view string_view
Definition: attr.cc:22
bloaty::DisassemblyInfo
Definition: bloaty.h:317
cs_malloc
CAPSTONE_EXPORT cs_insn *CAPSTONE_API cs_malloc(csh ud)
Definition: cs.c:1052
X86_INS_JGE
@ X86_INS_JGE
Definition: x86.h:646
input
std::string input
Definition: bloaty/third_party/protobuf/src/google/protobuf/io/tokenizer_unittest.cc:197
cs_free
CAPSTONE_EXPORT void CAPSTONE_API cs_free(cs_insn *insn, size_t count)
Definition: cs.c:1039
handle
static csh handle
Definition: test_arm_regression.c:16
X86_INS_JECXZ
@ X86_INS_JECXZ
Definition: x86.h:644
iter
Definition: test_winkernel.cpp:47
util.h
bloaty::RangeMap::TryGetLabel
bool TryGetLabel(uint64_t addr, std::string *label) const
Definition: range_map.cc:97
bloaty::ReImpl::GlobalReplace
static ABSL_ATTRIBUTE_NORETURN int GlobalReplace(std::string *, const ReImpl &, std::string)
Definition: bloaty/src/re.h:79
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
absl::string_view::data
constexpr const_pointer data() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:336
to_string
static bool to_string(zval *from)
Definition: protobuf/php/ext/google/protobuf/convert.c:333
X86_INS_LEA
@ X86_INS_LEA
Definition: x86.h:708
op
static grpc_op * op
Definition: test/core/fling/client.cc:47
X86_INS_JNP
@ X86_INS_JNP
Definition: x86.h:653
pair
std::pair< std::string, std::string > pair
Definition: abseil-cpp/absl/container/internal/raw_hash_set_benchmark.cc:78
X86_REG_RIP
@ X86_REG_RIP
Definition: x86.h:29
setup.target
target
Definition: third_party/bloaty/third_party/protobuf/python/setup.py:179
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
X86_INS_JBE
@ X86_INS_JBE
Definition: x86.h:641
X86_INS_JE
@ X86_INS_JE
Definition: x86.h:645


grpc
Author(s):
autogenerated on Fri May 16 2025 02:58:16