Skip to content

Commit 3b58483

Browse files
Add support to avoid header expansion
Previously, clang-extract only properly supported flags to expand headers. Now the new flag: ``` -DCE_NOT_EXPAND_INCLUDES=header1.h,...,headern.h ``` can be used to instruct it to not expand certain headers. To enable it, the expansion must go through the -DCE_KEEP_INCLUDES engine, which means it is only activated if a certain policy is enabled. Furthermore, this commit also adds a new program: `ce-includetree` which shows in stdout the IncludeTree of the input source file. it can be invoked using the compilation flags of the original file. Signed-off-by: Giuliano Belinassi <gbelinassi@suse.de>
1 parent 05a65a9 commit 3b58483

17 files changed

+565
-142
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ Clang-extract support many options which controls the output code:
205205
- `-DCE_KEEP_INCLUDES` Keep all possible `#include<file>` directives.
206206
- `-DCE_KEEP_INCLUDES=<policy>` Keep all possible `#include<file>` directives, but using the specified include expansion <policy>. Valid values are `nothing`, `everything`, `kernel`, `system` and `compiler`.
207207
- `-DCE_EXPAND_INCLUDES=<args>` Force expansion of the headers provided in <args>.
208+
- `-DCE_NOT_EXPAND_INCLUDES=<args>` Force the following headers to **not** be expanded.
208209
- `-DCE_RENAME_SYMBOLS` Allow renaming of extracted symbols.
209210
- `-DCE_DEBUGINFO_PATH=<arg>` Path to the compiled (ELF) object of the desired program to extract. This is used to decide if externalization is necessary or not for given symbol.
210211
- `-DCE_IPACLONES_PATH=<arg>` Path to gcc .ipa-clones files generated by gcc. Used to decide if desired function to extract was inlined into other functions.

TreeDump.cpp

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//===- TreeDump.cpp - Dump IncludeTree to stdout --*- C++ -*-===//
2+
//
3+
// This project is licensed under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
/// \file
10+
/// Entrypoint of the IncludeTree dump tool.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
/* Author: Giuliano Belinassi */
15+
16+
#include "ArgvParser.hh"
17+
#include "Passes.hh"
18+
#include "Error.hh"
19+
20+
#include <iostream>
21+
#include <stdio.h>
22+
23+
using namespace llvm;
24+
using namespace clang;
25+
26+
void print_usage_message(void)
27+
{
28+
llvm::outs() <<
29+
"OVERVIEW: Tool to show the tree of includes of a C/C++ file.\n"
30+
" It should be invoked as a C/C++ compiler.\n"
31+
"\n"
32+
"USAGE: ce-includetree [options] file...\n"
33+
"\n"
34+
"CLANG-EXTRACT OPTIONS:\n"
35+
" <clang-switch> A clang switch, as specified by calling clang --help.\n"
36+
" -D__KERNEL__ Indicate that we are processing a Linux sourcefile.\n"
37+
" -DCE_KEEP_INCLUDES Keep all possible #include<file> directives.\n"
38+
" -DCE_KEEP_INCLUDES=<policy>\n"
39+
" Keep all possible #include<file> directives, but using the\n"
40+
" specified include expansion <policy>. Valid values are\n"
41+
" nothing, everything, kernel, system and compiler.\n"
42+
" -DCE_EXPAND_INCLUDES=<args>\n"
43+
" Force expansion of the headers provided in <args>.\n"
44+
" -DCE_NOT_EXPAND_INCLUDES=<args>\n"
45+
" Force the following headers to NOT be expanded.\n"
46+
"\n";
47+
}
48+
49+
int main(int argc, char **argv)
50+
{
51+
ArgvParser args(argc, argv);
52+
PassManager::Context ctx(args);
53+
54+
if (argc <= 1) {
55+
print_usage_message();
56+
return 0;
57+
}
58+
59+
/* Cleverly silence any error from clang. */
60+
fclose(stderr);
61+
if (Build_ASTUnit(&ctx) == false){
62+
llvm::outs() << "Unable to create ASTUnit of " << ctx.InputPath << '\n';
63+
return 1;
64+
}
65+
66+
const DiagnosticsEngine &de = ctx.AST->getDiagnostics();
67+
if (de.hasErrorOccurred()) {
68+
llvm::outs() << "ASTUnit of " << ctx.InputPath << " contain errors. Aborting.\n";
69+
return 1;
70+
}
71+
72+
IncludeTree IT(ctx.AST.get(), ctx.IncExpansionPolicy, ctx.HeadersToExpand,
73+
ctx.HeadersToNotExpand);
74+
IT.Dump(llvm::outs());
75+
76+
return 0;
77+
}

libcextract/ArgvParser.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ ArgvParser::ArgvParser(int argc, char **argv)
6161
FunctionsToExtract(),
6262
SymbolsToExternalize(),
6363
HeadersToExpand(),
64+
HeadersToNotExpand(),
6465
OutputFile(),
6566
IgnoreClangErrors(false),
6667
DisableExternalization(false),
@@ -156,6 +157,8 @@ void ArgvParser::Print_Usage_Message(void)
156157
" nothing, everything, kernel, system and compiler.\n"
157158
" -DCE_EXPAND_INCLUDES=<args>\n"
158159
" Force expansion of the headers provided in <args>.\n"
160+
" -DCE_NOT_EXPAND_INCLUDES=<args>\n"
161+
" Force the following headers to NOT be expanded.\n"
159162
" -DCE_RENAME_SYMBOLS Allow renaming of extracted symbols.\n"
160163
" -DCE_DEBUGINFO_PATH=<arg>\n"
161164
" Path to the compiled (ELF) object of the desired program to\n"
@@ -255,6 +258,11 @@ bool ArgvParser::Handle_Clang_Extract_Arg(const char *str)
255258

256259
return true;
257260
}
261+
if (prefix("-DCE_NOT_EXPAND_INCLUDES=", str)) {
262+
HeadersToNotExpand = Extract_Args(str);
263+
264+
return true;
265+
}
258266
if (prefix("-DCE_DEBUGINFO_PATH=", str)) {
259267
Debuginfos = Extract_Args(str);
260268

libcextract/ArgvParser.hh

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ class ArgvParser
5959
return HeadersToExpand;
6060
}
6161

62+
inline std::vector<std::string>& Get_Headers_To_Not_Expand(void)
63+
{
64+
return HeadersToNotExpand;
65+
}
66+
6267
inline std::string &Get_Output_File(void)
6368
{
6469
return OutputFile;
@@ -139,8 +144,6 @@ class ArgvParser
139144
return IgnoreClangErrors;
140145
}
141146

142-
const char *Get_Input_File(void);
143-
144147
/** Print help usage message. */
145148
void Print_Usage_Message(void);
146149

@@ -153,6 +156,7 @@ class ArgvParser
153156
std::vector<std::string> FunctionsToExtract;
154157
std::vector<std::string> SymbolsToExternalize;
155158
std::vector<std::string> HeadersToExpand;
159+
std::vector<std::string> HeadersToNotExpand;
156160
std::string OutputFile;
157161

158162
bool IgnoreClangErrors;

libcextract/Error.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ DiagsClass DiagsClass::sDiag;
2828
DiagsClass::DiagsClass(void)
2929
: LangOpts(),
3030
DOpts(DiagnosticOptionsWithColor()),
31-
DiagsEngine(llvm::outs(), LangOpts, DOpts.getDiagsOptsToEngine())
31+
DiagsEngine(llvm::errs(), LangOpts, DOpts.getDiagsOptsToEngine())
3232
{}
3333

3434
/* Print error giving a piece of source code that caused the error. */
@@ -46,6 +46,6 @@ void DiagsClass::EmitMessage(const StringRef message, DiagnosticsEngine::Level l
4646
{
4747
bool colored = Is_Colored();
4848
const std::string ce_message = Append_CE(message);
49-
TextDiagnostic::printDiagnosticLevel(llvm::outs(), level, colored);
50-
TextDiagnostic::printDiagnosticMessage(llvm::outs(), false, ce_message, 0, 0, colored);
49+
TextDiagnostic::printDiagnosticLevel(llvm::errs(), level, colored);
50+
TextDiagnostic::printDiagnosticMessage(llvm::errs(), false, ce_message, 0, 0, colored);
5151
}

libcextract/ExpansionPolicy.cpp

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,6 @@
2121
bool KernelExpansionPolicy::Must_Expand(const StringRef &absolute_path,
2222
const StringRef &relative_path)
2323
{
24-
// absolute_path and relative_path are different when extracting code from a
25-
// compiled kernel directory, so we need to check whether the include paths
26-
// start from include paths.
27-
if (absolute_path != relative_path)
28-
return !relative_path.starts_with("./include");
29-
3024
std::vector<std::string> include_paths = { "/include/", "/arch/" };
3125

3226
for (auto &path : include_paths) {
@@ -75,6 +69,12 @@ bool CompilerExpansionPolicy::Must_Expand(const StringRef &absolute_path,
7569
return true;
7670
}
7771

72+
bool CompilerExpansionPolicy::Must_Not_Expand(const StringRef &absolute_path,
73+
const StringRef &relative_path)
74+
{
75+
return !Must_Expand(absolute_path, relative_path);
76+
}
77+
7878
std::unique_ptr<IncludeExpansionPolicy> IncludeExpansionPolicy::Get_Expansion_Policy_Unique(
7979
IncludeExpansionPolicy::Policy p)
8080
{
@@ -134,3 +134,22 @@ IncludeExpansionPolicy::Policy IncludeExpansionPolicy::Get_From_String(const cha
134134

135135
return IncludeExpansionPolicy::NOTHING;
136136
}
137+
138+
139+
/* Return true if headers passed through -include must be expanded. */
140+
bool IncludeExpansionPolicy::Expand_Minus_Includes(IncludeExpansionPolicy::Policy policy)
141+
{
142+
switch (policy) {
143+
case INVALID:
144+
case EVERYTHING:
145+
case SYSTEM:
146+
case COMPILER:
147+
return true;
148+
break;
149+
150+
case NOTHING:
151+
case KERNEL:
152+
return false;
153+
break;
154+
}
155+
}

libcextract/ExpansionPolicy.hh

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ class IncludeExpansionPolicy
2525
public:
2626
virtual bool Must_Expand(const StringRef &absolute_path, const StringRef &relative_path) = 0;
2727

28+
virtual bool Must_Not_Expand(const StringRef &absolute_path, const StringRef &relative_path) = 0;
29+
30+
2831
virtual ~IncludeExpansionPolicy() = default;
2932

3033
enum Policy {
@@ -36,10 +39,12 @@ class IncludeExpansionPolicy
3639
COMPILER,
3740
};
3841

39-
static IncludeExpansionPolicy *Get_Expansion_Policy(Policy policy);
4042
static std::unique_ptr<IncludeExpansionPolicy>
4143
Get_Expansion_Policy_Unique(Policy policy);
4244

45+
/* Return if headers passed through -include must be expanded. */
46+
static bool Expand_Minus_Includes(Policy policy);
47+
4348
static Policy Get_From_String(const char *string);
4449
inline static Policy Get_Overriding(const char *string, bool is_kernel)
4550
{
@@ -66,6 +71,11 @@ class NoIncludeExpansionPolicy : public IncludeExpansionPolicy
6671
return false;
6772
}
6873

74+
virtual bool Must_Not_Expand(const StringRef &absolute_path, const StringRef &relative_path)
75+
{
76+
return false;
77+
}
78+
6979
};
7080

7181
class ExpandEverythingExpansionPolicy : public IncludeExpansionPolicy
@@ -75,25 +85,41 @@ class ExpandEverythingExpansionPolicy : public IncludeExpansionPolicy
7585
{
7686
return true;
7787
}
88+
89+
virtual bool Must_Not_Expand(const StringRef &absolute_path, const StringRef &relative_path)
90+
{
91+
return false;
92+
}
7893
};
7994

8095
/** Expand any header according to kernel livepatching rules. */
8196
class KernelExpansionPolicy : public IncludeExpansionPolicy
8297
{
8398
public:
8499
virtual bool Must_Expand(const StringRef &absolute_path, const StringRef &relative_path);
100+
101+
virtual bool Must_Not_Expand(const StringRef &absolute_path, const StringRef &relative_path)
102+
{
103+
return false;
104+
}
85105
};
86106

87107
/** Expand any header that is not installed in the system. */
88108
class SystemExpansionPolicy : public IncludeExpansionPolicy
89109
{
90110
public:
91111
virtual bool Must_Expand(const StringRef &absolute_path, const StringRef &relative_path);
112+
113+
virtual bool Must_Not_Expand(const StringRef &absolute_path, const StringRef &relative_path)
114+
{
115+
return false;
116+
}
92117
};
93118

94119
/** Expand any header that is not compiler-specific. */
95120
class CompilerExpansionPolicy : public IncludeExpansionPolicy
96121
{
97122
public:
98123
virtual bool Must_Expand(const StringRef &absolute_path, const StringRef &relative_path);
124+
virtual bool Must_Not_Expand(const StringRef &absolute_path, const StringRef &relative_path);
99125
};

libcextract/FunctionDepsFinder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
/** FunctionDependencyFinder class methods implementation. */
2525
FunctionDependencyFinder::FunctionDependencyFinder(PassManager::Context *ctx)
2626
: AST(ctx->AST.get()),
27-
IT(AST, ctx->IncExpansionPolicy, ctx->HeadersToExpand),
27+
IT(AST, ctx->IncExpansionPolicy, ctx->HeadersToExpand, ctx->HeadersToNotExpand),
2828
KeepIncludes(ctx->KeepIncludes),
2929
Visitor(AST)
3030
{

0 commit comments

Comments
 (0)