Skip to content

Commit

Permalink
Merge branch 'junghee/align-indall-target' into 'main'
Browse files Browse the repository at this point in the history
Generate alignments for functions

Closes #617 and debloating/dykondo#129

See merge request rewriting/ddisasm!1224
  • Loading branch information
jdorn-gt committed Nov 8, 2024
2 parents e09e352 + 69126fd commit 76ddcab
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 21 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
* Fixed bug that could result in missed symbolic expressions with TLS variables for `local-executable` TLS model
* Fix bug that caused assembling error due to wrong `symbol_minus_symbol`
for lsda entries with references to the end of `.gcc_except_table`
* Generate alignments for function entry blocks depending on address

# 1.9.0

Expand Down
11 changes: 11 additions & 0 deletions examples/ex_memberFunction/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
CXX="g++"
EXEC=

all: ex.cpp
$(CXX) ex.cpp $(CXXFLAGS) -o ex
@ $(EXEC) ./ex > out.txt
clean:
rm -f ex ex.unstripped out.txt *.s *.lib *.exp *.o *.err *.gtirb
check:
@ $(EXEC) ./ex >/tmp/res.txt
@ diff out.txt /tmp/res.txt && echo TEST OK
37 changes: 37 additions & 0 deletions examples/ex_memberFunction/ex.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include <stdio.h>
#include <stdlib.h>

class a
{
public:
void foo();

private:
__attribute__((visibility("hidden"))) void bar();
void baz() __attribute__((weak));
};

void a::foo()
{
printf("foo\n");
this->bar();
this->baz();
}

void a::bar()
{
printf("bar\n");
}

void a::baz()
{
printf("baz\n");
}

int main()
{
a *a1;
a1 = new a();
a1->foo();
return 0;
}
27 changes: 26 additions & 1 deletion src/datalog/main.dl
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,11 @@ instruction_get_dest_op(EA,Index,Op):-
next(EA,EA+Size):-
instruction(EA,Size,_,_,_,_,_,_,_,_).

.decl pc_relative_operand(src:address,index:operand_index, dest:address)
/**
EA has a PC-relative operand at Index, which is computed and stored in Dest.
NOTE: Currently, we define pc_relative_operand only for X64.
*/
.decl pc_relative_operand(EA:address,Index:operand_index,Dest:address)

pc_relative_operand(EA,Index,Dest):-
binary_isa("X64"),
Expand Down Expand Up @@ -688,6 +692,19 @@ halt(EA):-
arch.halt_operation(Operation),
instruction_get_operation(EA,Operation).

/**
Find alignment depending on EA
*/
.decl alignment_from_address(EA:address,AlignInBits:unsigned) inline

alignment_from_address(EA, AlignInBits):-
(
EA % 16 = 0, AlignInBits = 16;
EA % 16 != 0, EA % 8 = 0, AlignInBits = 8;
EA % 8 != 0, EA % 4 = 0, AlignInBits = 4;
EA % 4 != 0, EA % 2 = 0, AlignInBits = 2
).

/**
Auxiliary predicate that builds initial alignments from `alignment_required`:
the max alignment is picked for an EA later.
Expand All @@ -707,6 +724,14 @@ alignment_candidate(DataEA, AlignInBits):-
DataEA >= Begin,
DataEA < End.

// In addition to global/weak functions,
// some local functions may need alignments: e.g., member function pointers
// (https://itanium-cxx-abi.github.io/cxx-abi/abi.html#member-function-pointers)
// As the simplest solution, add alignment to each function
alignment_candidate(FuncEA,AlignInBits):-
function_inference.function_entry(FuncEA),
alignment_from_address(FuncEA,AlignInBits).

/**
Information about alignment in bits for a given address
*/
Expand Down
44 changes: 25 additions & 19 deletions src/passes/Disassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,7 @@ void buildCodeBlocks(gtirb::Context &Context, gtirb::Module &Module,
{
auto BlockInfo =
convertSortedRelation<VectorByEA<BlockInformation>>("block_information", Program);

for(auto &Tuple : *Program.getRelation("refined_block"))
{
gtirb::Addr BlockAddress;
Expand Down Expand Up @@ -743,16 +744,6 @@ void buildDataBlocks(gtirb::Context &Context, gtirb::Module &Module,
convertSortedRelation<std::set<gtirb::Addr>>("data_object_boundary", Program);
auto SymbolicExprAttributes = convertSortedRelation<VectorByEA<SymbolicExprAttribute>>(
"symbolic_expr_attribute", Program);
auto Alignments = convertSortedRelation<VectorByEA<Alignment>>("alignment", Program);

auto *Alignment = Module.getAuxData<gtirb::schema::Alignment>();
if(!Alignment)
{
// Create one if none exists.
std::map<gtirb::UUID, uint64_t> Tmp;
Module.addAuxData<gtirb::schema::Alignment>(std::move(Tmp));
Alignment = Module.getAuxData<gtirb::schema::Alignment>();
}

std::map<gtirb::UUID, std::string> TypesTable;

Expand Down Expand Up @@ -831,22 +822,36 @@ void buildDataBlocks(gtirb::Context &Context, gtirb::Module &Module,
std::cerr << "ByteInterval at address " << CurrentAddr << " not found" << std::endl;
exit(1);
}

if(DataBlock && Alignment)
{
const auto AlignInfo = Alignments.find(*DataBlock->getAddress());
if(AlignInfo != Alignments.end())
{
(*Alignment)[DataBlock->getUUID()] = AlignInfo->Num;
}
}
}
}
buildBSS(Context, Module, Program);
Module.addAuxData<gtirb::schema::Encodings>(std::move(TypesTable));
Module.addAuxData<gtirb::schema::SymbolicExpressionSizes>(std::move(SymbolicSizes));
}

void buildAlignments(gtirb::Module &Module, souffle::SouffleProgram &Program)
{
auto Alignments = convertSortedRelation<VectorByEA<Alignment>>("alignment", Program);

auto *Alignment = Module.getAuxData<gtirb::schema::Alignment>();
if(!Alignment)
{
// Create one if none exists.
std::map<gtirb::UUID, uint64_t> Tmp;
Module.addAuxData<gtirb::schema::Alignment>(std::move(Tmp));
Alignment = Module.getAuxData<gtirb::schema::Alignment>();
}

for(auto &AlignInfo : Alignments)
{
if(auto BlockIt = Module.findBlocksAt(AlignInfo.EA); !BlockIt.empty())
{
gtirb::Node &Block = BlockIt.front();
(*Alignment)[Block.getUUID()] = AlignInfo.Num;
}
}
}

void connectSymbolsToBlocks(gtirb::Context &Context, gtirb::Module &Module,
souffle::SouffleProgram &Program)
{
Expand Down Expand Up @@ -1627,6 +1632,7 @@ void disassembleModule(gtirb::Context &Context, gtirb::Module &Module,
buildSymbolForwarding(Context, Module, Program);
buildCodeBlocks(Context, Module, Program);
buildDataBlocks(Context, Module, Program);
buildAlignments(Module, Program);
buildCodeSymbolicInformation(Module, Program);
buildCfiDirectives(Module, Program);
buildSehTable(Module, Program);
Expand Down
30 changes: 29 additions & 1 deletion tests/misc_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,10 @@ def test_aligned_data_in_code(self):
alignment_list = [
alignment
for block, alignment in alignments
if block.address > main_block.address
if (
block.address > main_block.address
and block in m.data_blocks
)
]

# alignment=16: `data128.1`, `data128.2`
Expand Down Expand Up @@ -506,6 +509,31 @@ def test_aligned_data_in_code_avx512f(self):
# alignment=64: `data512`
self.assertEqual(alignment_list.count(64), 1)

@unittest.skipUnless(
platform.system() == "Linux", "This test is linux only."
)
def test_func_align(self):
"""
Test that alignment directives are correctly generated for functions.
"""
binary = "ex"
with cd(ex_dir / "ex_memberFunction"):
self.assertTrue(compile("gcc", "g++", "-O0", []))
ir = disassemble(Path(binary)).ir()
m = ir.modules[0]

funcs = ["_ZN1a3fooEv", "_ZN1a3barEv", "_ZN1a3bazEv"]
# ------------- ------------- -------------
# global local weak

func_blocks = [
next(m.symbols_named(sym)).referent for sym in funcs
]

alignments = m.aux_data["alignment"].data

self.assertTrue(all(b in alignments for b in func_blocks))


class RawGtirbTests(unittest.TestCase):
@unittest.skipUnless(
Expand Down

0 comments on commit 76ddcab

Please sign in to comment.