Skip to content

Commit a5344ce

Browse files
cblichmanncopybara-github
authored andcommitted
Shorter generated function names, unify address rendering
- Skip leading zeroes `sub_00401245` -> `sub_401245`, like IDA Pro and Binary Ninja - Generate all function names and addresses from a single place - Drive-by: Fix comparison in `HumanReadableDuration()` PiperOrigin-RevId: 482440847 Change-Id: I684aef88abac6d2a04b808b26d4927af4cb1cf23
1 parent c2b1ad0 commit a5344ce

File tree

8 files changed

+46
-25
lines changed

8 files changed

+46
-25
lines changed

basic_block.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
#include <ostream>
1919

2020
#include "third_party/zynamics/binexport/call_graph.h"
21+
#include "third_party/zynamics/binexport/util/format.h"
22+
23+
using security::binexport::FormatAddress;
2124

2225
BasicBlock::Cache BasicBlock::cache_;
2326

@@ -57,8 +60,7 @@ BasicBlock* BasicBlock::Create(BasicBlockInstructions* instructions) {
5760
void BasicBlock::Render(std::ostream* stream, const CallGraph& call_graph,
5861
const FlowGraph& flow_graph) const {
5962
for (const auto& instruction : *this) {
60-
*stream << std::hex << std::setfill('0') << std::uppercase << std::setw(8)
61-
<< instruction.GetAddress() << " ";
63+
*stream << FormatAddress(instruction.GetAddress()) << " ";
6264
instruction.Render(stream, flow_graph);
6365
std::pair<Comments::const_iterator, Comments::const_iterator> comments =
6466
call_graph.GetComments(instruction.GetAddress());

call_graph.cc

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,11 @@
2020
#include <ostream>
2121

2222
#include "third_party/zynamics/binexport/flow_graph.h"
23+
#include "third_party/zynamics/binexport/util/format.h"
2324
#include "third_party/zynamics/binexport/util/hash.h"
2425

26+
using security::binexport::FormatAddress;
27+
2528
namespace {
2629

2730
bool EdgeFunctionIsNull(const EdgeInfo& edge) { return edge.function_ == 0; }
@@ -59,8 +62,8 @@ void CallGraph::Render(std::ostream* stream,
5962
const FlowGraph& flow_graph) const {
6063
for (const auto& function_address : functions_) {
6164
const Function* function = flow_graph.GetFunction(function_address);
62-
*stream << std::hex << std::setfill('0') << std::uppercase << std::setw(8)
63-
<< function_address << " " << std::setfill(' ') << std::setw(8)
65+
*stream << FormatAddress(function_address) << " " << std::setfill(' ')
66+
<< std::setw(8)
6467
<< (function->GetType(false) != Function::TYPE_STANDARD
6568
? Function::GetTypeName(function->GetType(false))
6669
: "")
@@ -81,11 +84,9 @@ void CallGraph::Render(std::ostream* stream,
8184

8285
for (const auto& edge : edges_) {
8386
const Function* function = flow_graph.GetFunction(edge.target_);
84-
*stream << std::hex << std::setfill('0') << std::uppercase << std::setw(8)
85-
<< edge.function_->GetEntryPoint() << ":" << std::hex
86-
<< std::setfill('0') << std::uppercase << std::setw(8)
87-
<< edge.source_ << " -> " << std::hex << std::setfill('0')
88-
<< std::uppercase << std::setw(8) << edge.target_ << " "
87+
*stream << FormatAddress(edge.function_->GetEntryPoint()) << ":"
88+
<< FormatAddress(edge.source_) << " -> "
89+
<< FormatAddress(edge.target_) << " "
8990
<< edge.function_->GetName(Function::DEMANGLED) << " -> "
9091
<< (function ? function->GetName(Function::DEMANGLED) : "") << "\n";
9192
}

dump_writer.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "third_party/zynamics/binexport/call_graph.h"
2121
#include "third_party/zynamics/binexport/flow_graph.h"
22+
#include "third_party/zynamics/binexport/util/format.h"
2223

2324
namespace security::binexport {
2425

function.cc

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,12 @@
2424

2525
#include "third_party/absl/log/check.h"
2626
#include "third_party/absl/log/log.h"
27-
#include "third_party/absl/strings/ascii.h"
2827
#include "third_party/absl/strings/str_cat.h"
2928
#include "third_party/zynamics/binexport/call_graph.h"
29+
#include "third_party/zynamics/binexport/util/format.h"
30+
31+
using security::binexport::FormatAddress;
32+
using security::binexport::FormatFunctionName;
3033

3134
int Function::instance_count_ = 0;
3235
Function::StringCache Function::string_cache_;
@@ -48,19 +51,16 @@ Function::~Function() {
4851

4952
void Function::Render(std::ostream* stream, const CallGraph& call_graph,
5053
const FlowGraph& flow_graph) const {
51-
*stream << std::hex << std::setfill('0') << std::uppercase << std::setw(8)
52-
<< GetEntryPoint() << " " << GetModuleName()
54+
*stream << FormatAddress(GetEntryPoint()) << " " << GetModuleName()
5355
<< (GetModuleName().empty() ? "" : ".") << GetName(DEMANGLED) << "\n";
5456
for (const auto& basic_block_ptr : basic_blocks_) {
5557
basic_block_ptr->Render(stream, call_graph, flow_graph);
5658
*stream << "\n";
5759
}
5860

5961
for (const auto& edge : edges_) {
60-
*stream << std::hex << std::setfill('0') << std::uppercase << std::setw(8)
61-
<< edge.source << " -> " << std::hex << std::setfill('0')
62-
<< std::uppercase << std::setw(8) << edge.target << " "
63-
<< edge.GetTypeName() << "\n";
62+
*stream << FormatAddress(edge.source) << " -> "
63+
<< FormatAddress(edge.target) << " " << edge.GetTypeName() << "\n";
6464
}
6565
if (!edges_.empty()) {
6666
*stream << "\n";
@@ -140,8 +140,7 @@ std::string Function::GetName(Name type) const {
140140
if (HasRealName()) {
141141
return type == MANGLED || demangled_name_.empty() ? name_ : demangled_name_;
142142
}
143-
return absl::StrCat("sub_", absl::AsciiStrToUpper(absl::StrCat(absl::Hex(
144-
GetEntryPoint(), absl::kZeroPad8))));
143+
return FormatFunctionName(GetEntryPoint());
145144
}
146145

147146
bool Function::HasRealName() const { return !name_.empty(); }
@@ -198,9 +197,8 @@ int Function::GetBasicBlockIndexForAddress(Address address) const {
198197
}
199198
}
200199

201-
LOG(WARNING) << absl::StrCat("No basic block for ",
202-
absl::Hex(address, absl::kZeroPad8), " in ",
203-
GetEntryPoint());
200+
LOG(WARNING) << absl::StrCat("No basic block for ", FormatAddress(address),
201+
" in ", GetEntryPoint());
204202
return basic_blocks_.size();
205203
}
206204

reader/call_graph.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "third_party/absl/memory/memory.h"
2323
#include "third_party/absl/strings/str_cat.h"
2424
#include "third_party/zynamics/binexport/reader/graph_utility.h"
25+
#include "third_party/zynamics/binexport/util/format.h"
2526

2627
namespace security::binexport {
2728

@@ -57,7 +58,7 @@ void VertexPropertyFromVertexProto(const BinExport2::CallGraph::Vertex& vertex,
5758
vertex_property->flags |= CallGraph::kVertexName;
5859
}
5960
if (!(vertex_property->flags & CallGraph::kVertexName)) {
60-
vertex_property->name = absl::StrCat("sub_", absl::Hex(vertex.address()));
61+
vertex_property->name = FormatFunctionName(vertex.address());
6162
}
6263
if (vertex.has_module_index()) {
6364
vertex_property->module_name = proto.module(vertex.module_index()).name();

util/format.cc

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ std::string FormatAddress(Address address) {
1717
return absl::StrFormat("%016X", address);
1818
}
1919

20+
std::string FormatFunctionName(Address address) {
21+
return absl::StrFormat("sub_%X", address);
22+
}
23+
2024
std::string HumanReadableDuration(double seconds) {
2125
std::string result;
2226

@@ -38,9 +42,9 @@ std::string HumanReadableDuration(double seconds) {
3842
absl::StrAppend(&result, (need_space ? " " : ""), full_minutes, "m");
3943
need_space = true;
4044
}
41-
if (full_seconds > 0 || absl::ToInt64Milliseconds(full) > 0) {
45+
if (full_seconds > 0 || full > absl::ZeroDuration()) {
4246
absl::StrAppend(&result, (need_space ? " " : ""), full_seconds);
43-
if (absl::ToInt64Milliseconds(full) > 0) {
47+
if (full > absl::ZeroDuration()) {
4448
absl::StrAppend(&result, ".", absl::ToInt64Milliseconds(full) / 10);
4549
}
4650
absl::StrAppend(&result, "s");

util/format.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
namespace security::binexport {
2424

25-
// Returns a hexadecimal string representation of an address suitable for log
25+
// Returns a hexadecimal string representation of an address, suitable for log
2626
// lines and display in UIs. The returned string will always be either 8 or 16
2727
// uppercase hexadecimal characters, depending on whether the address is larger
2828
// than 0xFFFFFFFF. In any case, the string is left padded with zeroes.
@@ -34,6 +34,12 @@ namespace security::binexport {
3434
// FormatAddress(0x7FF00000004926F4) => "7FF00000004926F4"
3535
std::string FormatAddress(Address address);
3636

37+
// Returns an artificial name for the function at address, suitable for display
38+
// in UIs. The returned string will start with "sub_" and uppercase hexadecmial
39+
// characters. The address is _not_ formatted with leading zeroes, following
40+
// what IDA Pro and Binary Ninja do.
41+
std::string FormatFunctionName(Address address);
42+
3743
// Formats a duration given in seconds or as an absl::Duration into a human
3844
// readable time based on hours. Maximum precision is 1/100th of a second.
3945
//

util/format_test.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ TEST(FormatUtilTest, FormatAddress) {
2929
EXPECT_THAT(FormatAddress(0x7FF00000004926F4), StrEq("7FF00000004926F4"));
3030
}
3131

32+
TEST(FormatUtilTest, FormatFunctionName) {
33+
EXPECT_THAT(FormatFunctionName(0x08), StrEq("sub_8"));
34+
EXPECT_THAT(FormatFunctionName(0x59DE50), StrEq("sub_59DE50"));
35+
EXPECT_THAT(FormatFunctionName(0x00000001004940B0), StrEq("sub_1004940B0"));
36+
EXPECT_THAT(FormatFunctionName(0x7FF00000004926F4),
37+
StrEq("sub_7FF00000004926F4"));
38+
}
39+
3240
TEST(FormatUtilTest, HumanReadableDuration) {
3341
EXPECT_THAT(HumanReadableDuration(3600), StrEq("1h"));
3442
EXPECT_THAT(HumanReadableDuration(1800), StrEq("30m"));

0 commit comments

Comments
 (0)