├── .gitignore
├── CMakeLists.txt
├── LICENSE
├── README.md
├── images
└── bruh.jpg
├── include
├── DemanglePass.h
├── Demangler.h
├── DetrampolinePass.h
├── Detrampoliner.h
└── logging.h
├── src
├── DemanglePass.cpp
├── Demangler.cpp
├── DetrampolinePass.cpp
├── Detrampoliner.cpp
└── main.cpp
└── test
├── cpp
├── main-proc.ll
├── main.bc
├── main.cpp
└── main.ll
├── objc
├── main
├── main-proc.ll
├── main.bc
├── main.ll
└── main.m
├── rust
├── main
├── main-proc.ll
├── main.bc
├── main.ll
└── main.rs
└── swift
├── main-proc.ll
├── main.bc
├── main.ll
└── main.swift
/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode
2 | build/
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ## TODO: documentation building via doxy, zlib for xar reading (future),
2 | cmake_minimum_required(VERSION 3.20)
3 |
4 | project(bruh)
5 |
6 | set(CMAKE_CXX_VERSION 20)
7 | set(CMAKE_OSX_DEPLOYMENT_TARGET "11.1" CACHE STRING "Minimum OSX Deployment Version")
8 |
9 | option(SWIFT_SOURCE_PATH "Path to the Swift source code")
10 | option(SWIFT_BUILD_PATH "Path to the Swift build path")
11 |
12 | find_package(LLVM REQUIRED CONFIG)
13 | message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
14 | message(STATUS "Found LLVM-Config.cmake in ${LLVM_DIR}")
15 |
16 | if (CMAKE_COMPILER_IS_GNUXX)
17 | add_definitions(-std=c++20 -fPIC)
18 | add_definitions(-fno-rtti)
19 | elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
20 | add_definitions(-std=c++20 -stdlib=libc++)
21 | add_definitions(-fno-rtti)
22 | endif()
23 |
24 | set(BRUH_SRC
25 | src/main.cpp
26 | src/Demangler.cpp
27 | src/DemanglePass.cpp
28 | src/Detrampoliner.cpp
29 | src/DetrampolinePass.cpp
30 | )
31 |
32 | set(BRUH_INCLUDES
33 | include/Demangler.h
34 | include/DemanglePass.h
35 | include/Detrampoliner.h
36 | include/DetrampolinePass.h
37 | include/logging.h
38 | )
39 |
40 | set(SWIFT_AST_INCLUDES
41 | ${SWIFT_SOURCE_PATH}/include/swift/AST/ReferenceStorage.def
42 | )
43 |
44 | set(SWIFT_DEMANGLING_INCLUDES
45 | ${SWIFT_SOURCE_PATH}/include/swift/Demangling/Demangle.h
46 | ${SWIFT_SOURCE_PATH}/include/swift/Demangling/Demangler.h
47 | ${SWIFT_SOURCE_PATH}/include/swift/Demangling/DemangleNodes.def
48 | ${SWIFT_SOURCE_PATH}/include/swift/Demangling/ManglingMacros.h
49 | ${SWIFT_SOURCE_PATH}/include/swift/Demangling/ManglingUtils.h
50 | ${SWIFT_SOURCE_PATH}/include/swift/Demangling/NamespaceMacros.h
51 | ${SWIFT_SOURCE_PATH}/include/swift/Demangling/Punycode.h
52 | ${SWIFT_SOURCE_PATH}/include/swift/Demangling/StandardTypesMangling.def
53 | ${SWIFT_SOURCE_PATH}/include/swift/Demangling/TypeDecoder.h
54 | ${SWIFT_SOURCE_PATH}/include/swift/Demangling/TypeLookupError.h
55 | ${SWIFT_SOURCE_PATH}/include/swift/Demangling/ValueWitnessMangling.def
56 | )
57 |
58 | message(STATUS "Swift Demangling Includes: ${SWIFT_DEMANGLING_INCLUDES}")
59 |
60 | add_executable(bruh
61 | ${BRUH_SRC}
62 | ${BRUH_INCLUDES}
63 |
64 | ${SWIFT_AST_INCLUDES}
65 | ${SWIFT_DEMANGLING_INCLUDES}
66 | )
67 |
68 | target_include_directories(bruh PRIVATE
69 | ${CMAKE_CURRENT_SOURCE_DIR}/include
70 | ${LLVM_INCLUDE_DIRS}
71 | ${SWIFT_SOURCE_PATH}/include/
72 | )
73 |
74 | # Thank you https://stackoverflow.com/questions/31422680/how-to-set-visual-studio-filters-for-nested-sub-directory-using-cmake
75 | function(assign_source_group)
76 | foreach(source IN ITEMS ${ARGN})
77 | # if not absolute path, make it so
78 | if (IS_ABSOLUTE "${source}")
79 | file(RELATIVE_PATH relative_source "${CMAKE_CURRENT_SOURCE_DIR}" "${source}")
80 | else()
81 | set(relative_source "${source}")
82 | endif()
83 |
84 | # get the directory name
85 | get_filename_component(directory_name "${relative_source}" PATH)
86 | # replace '/' with '\\' as per source_group documentation on subgroups
87 | string(REPLACE "/" "\\" source_path "${directory_name}")
88 | # make the source group
89 | source_group("${source_path}" FILES "${source}")
90 | endforeach()
91 | endfunction(assign_source_group)
92 |
93 | assign_source_group(${BRUH_SRC})
94 | assign_source_group(${BRUH_INCLUDES})
95 | assign_source_group(${SWIFT_DEMANGLING_INCLUDES})
96 | assign_source_group(${SWIFT_AST_INCLUDES})
97 |
98 | llvm_map_components_to_libnames(
99 | llvm_libs
100 | support
101 | core
102 | irreader
103 | object
104 | debuginfodwarf
105 | analysis
106 | )
107 |
108 | message(STATUS "Found LLVM Libs: ${llvm_libs}")
109 |
110 | target_link_libraries(bruh
111 | ${llvm_libs}
112 | ${SWIFT_BUILD_PATH}/lib/libswiftDemangling.a
113 | )
114 |
115 | install(TARGETS bruh RUNTIME DESTINATION bin)
116 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # BRUH (Bitcode, Readable for Us Humans)
2 |
3 | 
4 |
5 | `bruh` is a tool to make LLVM IR more human readable.
6 |
7 | Its intention is not to create valid IR for anything other than easier reading for humans.
8 |
9 | For example, it will take CallSites like these:
10 |
11 | ```llvm
12 | # objc
13 | %42 = call %0* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to %0* (i8*, i8*, i64)*)(i8* %41, i8* %40, i64 1)
14 |
15 | # cpp
16 | %6 = call nonnull align 8 dereferenceable(8) %"class.std::__1::basic_ostream"* @_ZNSt3__1lsINS_11char_traitsIcEEEERNS_13basic_ostreamIcT_EES6_PKc(%"class.std::__1::basic_ostream"* nonnull align 8 dereferenceable(8) %5, i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str, i64 0, i64 0)), !dbg !2452
17 |
18 | # Swift
19 | %17 = call swiftcc %swift.refcounted* @"$sScTss5Error_pRs_rlE8priority9operationScTyxsAA_pGScPSg_xyYaYbKcntcfC"(%TScPSg* noalias nocapture %6, i8* bitcast (%swift.async_func_pointer* @"$ss5Error_pIeghHzo_ytsAA_pIeghHrzo_TRTATu" to i8*), %swift.refcounted* %14, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @"$sytN", i32 0, i32 1))
20 |
21 | # Rust
22 | %0 = call nonnull i8* @"_ZN4core3ptr8non_null16NonNull$LT$T$GT$13new_unchecked17h52016c20d23e96b9E"(i8* %_2)
23 | ```
24 |
25 | And change them to:
26 |
27 | ```llvm
28 | # objc
29 | %42 = call %0* @"-[StringGetterer getStringFor:]"(i8* %41, i8* %40, i64 1)
30 |
31 | # cpp
32 | %6 = call nonnull align 8 dereferenceable(8) %"class.std::__1::basic_ostream"* @"std::__1::basic_ostream >& std::__1::operator<< >(std::__1::basic_ostream >&, char const*)"(%"class.std::__1::basic_ostream"* nonnull align 8 dereferenceable(8) %5, i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str, i64 0, i64 0)), !dbg !2452
33 |
34 | # Swift
35 | %17 = call swiftcc %swift.refcounted* @"(extension in Swift):Swift.Task< where B == Swift.Error>.init(priority: Swift.Optional, operation: __owned @Sendable () async throws -> A) -> Swift.Task"(%TScPSg* noalias nocapture %6, i8* bitcast (%swift.async_func_pointer* @"async function pointer to partial apply forwarder for reabstraction thunk helper from @escaping @callee_guaranteed @Sendable @async () -> (@error @owned Swift.Error) to @escaping @callee_guaranteed @Sendable @async () -> (@out (), @error @owned Swift.Error)" to i8*), %swift.refcounted* %14, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @"type metadata for ()", i32 0, i32 1))
36 | call void @swift_release(%swift.refcounted* %17) #5
37 |
38 | # Rust
39 | %0 = call nonnull i8* @"core::pitr::non_null::NonNull$LT$T$GT$::new_unchecked::h52016c20d23e96b9"(i8* %_2)
40 | ```
41 |
42 | ## Requirements
43 |
44 | - A modern build of Swift (has been tested with 5.10)
45 | - A modern build of LLVM (has been tested with 14.0)
46 | - A modern compiler (has been tested with Clang 13.0)
47 | - macOS
48 | - see [Limitations](#limitations)
49 |
50 | ## Building
51 |
52 | bruh uses the CMake build system, so create a build directory and run the following command:
53 |
54 | ```bash
55 | mkdir build && cd build
56 | cmake -GNinja -DSWIFT_BUILD_PATH="/path/to/swift/build/" -DSWIFT_SOURCE_PATH="/path/to/swift/source" ../
57 | ```
58 |
59 | Optionally, you may need to pass `-DLLVM_DIR` if you don't have LLVM on your `PATH`. You should use the Apple fork of the LLVM project - if you built Swift, you can use the same LLVM it uses. If you don't, you will see `Invalid record` errors when using `bruh`.
60 |
61 | ## Running
62 |
63 | Once built, bruh can be run from the command line like so:
64 |
65 | ```bash
66 | ❯ ./bruh --help
67 | OVERVIEW: bruh (Bitcode, Readable for Us Humans) v0.1
68 | USAGE: bruh [options]
69 |
70 | OPTIONS:
71 |
72 | General options:
73 |
74 | --processed= - Emit processed IR to this filepath, or stdout if nothing is provided
75 | --regular= - Emit unprocessed IR to this filepath
76 | ```
77 |
78 | There are a set of test files in `test//main.bc` that you can test, currently bruh requires a bitcode file - not a binary, or ll file.
79 |
80 | ### Example
81 |
82 | ```bash
83 | ./bruh --processed=test/objc/main-proc.ll test/objc/main.bc
84 | ```
85 |
86 | ## Limitations
87 |
88 | Currently, this tool (in the form provided) will only work on macOS, however if you recompile [Swifts Demangling library](https://github.com/apple/swift/tree/main/lib/Demangling) there shouldn't be an issue running this on linux. Support for linux will be added in the [Future](#future).
89 |
90 | ## Future
91 |
92 | - Linux support
93 | - Cleaning up of:
94 | - whitespace (explode structs to be readable etc)
95 | - call sites (placing arguments in the call name)
96 | - module printing for ease of reading
97 | - Collapse bitcasts as _most_ of the time you don't really need to read them
98 | - Def-Use/Call Flow annotations to easier follow usage of registers.
99 |
100 | ## License
101 |
102 | bruh is licensed under LGPL 3.0. See [LICENSE](LICENSE).
103 |
--------------------------------------------------------------------------------
/images/bruh.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NinjaLikesCheez/bruh/3e3bce65794be58b85cc2283fc01ecc1058575e4/images/bruh.jpg
--------------------------------------------------------------------------------
/include/DemanglePass.h:
--------------------------------------------------------------------------------
1 | //
2 | // DemanglePass.h
3 | // bruh
4 | //
5 | // Created by NinjaLikesCheez on 12/7/21.
6 | //
7 |
8 | #ifndef DEMANGLEPASS_H_
9 | #define DEMANGLEPASS_H_
10 |
11 | #include
12 |
13 | #include "Demangler.h"
14 |
15 | using llvm::BasicBlock;
16 | using llvm::Function;
17 | using llvm::GlobalVariable;
18 | using llvm::Instruction;
19 | using llvm::InstVisitor;
20 | using llvm::Module;
21 | using llvm::StructType;
22 | using llvm::Value;
23 |
24 | class DemanglePass : public InstVisitor {
25 | /// Module we're operating on
26 | const Module *module;
27 | Demangler *demangler;
28 |
29 | public:
30 | DemanglePass(const Module *module, Demangler *demangler) : module(module), demangler(demangler) { }
31 |
32 | // Compiler will be a hateful bastard if we don't define these
33 | void visit(Module &module) { InstVisitor::visit(module); }
34 | void visit(Function &function) { InstVisitor::visit(function); }
35 | void visit(BasicBlock &basicBlock) { InstVisitor::visit(basicBlock); }
36 | void visit(Instruction &instruction) { InstVisitor::visit(instruction); }
37 |
38 | void visitModule(Module &module);
39 | void visitFunction(Function &function);
40 | void visitBasicBlock(BasicBlock &basicBlock);
41 | void visitInstruction(Instruction &instruction);
42 |
43 | private:
44 | /// Demangles the name of a struct type
45 | void visitStructType(StructType *type);
46 |
47 | /// Demangles the name of a Global, as well as it's initializer
48 | void visitGlobal(GlobalVariable &global);
49 |
50 | /// Demangles the name of a value
51 | void visitValue(Value *value);
52 | };
53 |
54 |
55 | #endif // DEMANGLEPASS_H_
56 |
--------------------------------------------------------------------------------
/include/Demangler.h:
--------------------------------------------------------------------------------
1 | //
2 | // Demangler.h
3 | // bruh
4 | //
5 | // Created by NinjaLikesCheez on 23/11/2021.
6 | //
7 |
8 | #ifndef DEMANGLER_H_
9 | #define DEMANGLER_H_
10 |
11 | #include
12 |
13 | #include