1 /*
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
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
16 #include "disassembler.h"
17
18 #include "utils/logger.h"
19 #include "utils/pandargs.h"
20 #include "ark_version.h"
21 #include "file_format_version.h"
22
23 // NOLINTBEGIN(misc-non-private-member-variables-in-classes)
24 struct Options {
25 ark::PandArg<bool> help {"help", false, "Print this message and exit"};
26 ark::PandArg<bool> verbose {"verbose", false, "enable informative code output"};
27 ark::PandArg<bool> quiet {"quiet", false, "enables all of the --skip-* flags"};
28 ark::PandArg<bool> skipStrings {
29 "skip-string-literals", false,
30 "replaces string literals with their respectie id's, thus shortening emitted code size"};
31 ark::PandArg<bool> withSeparators {"with_separators", false,
32 "adds comments that separate sections in the output file"};
33 ark::PandArg<bool> debug {
34 "debug", false, "enable debug messages (will be printed to standard output if no --debug-file was specified) "};
35 ark::PandArg<std::string> debugFile {"debug-file", "",
36 "(--debug-file FILENAME) set debug file name. default is std::cout"};
37 ark::PandArg<std::string> inputFile {"input_file", "", "Path to the source binary code"};
38 ark::PandArg<std::string> outputFile {"output_file", "", "Path to the generated assembly code"};
39 ark::PandArg<std::string> profile {"profile", "", "Path to the profile"};
40 ark::PandArg<bool> version {"version", false,
41 "Ark version, file format version and minimum supported file format version"};
42
OptionsOptions43 explicit Options(ark::PandArgParser &paParser)
44 {
45 paParser.Add(&help);
46 paParser.Add(&verbose);
47 paParser.Add(&quiet);
48 paParser.Add(&skipStrings);
49 paParser.Add(&debug);
50 paParser.Add(&debugFile);
51 paParser.Add(&version);
52 paParser.PushBackTail(&inputFile);
53 paParser.PushBackTail(&outputFile);
54 paParser.Add(&profile);
55 paParser.EnableTail();
56 }
57 };
58 // NOLINTEND(misc-non-private-member-variables-in-classes)
59
PrintHelp(ark::PandArgParser & paParser)60 static void PrintHelp(ark::PandArgParser &paParser)
61 {
62 std::cerr << "Usage:" << std::endl;
63 std::cerr << "ark_disasm [options] input_file output_file" << std::endl << std::endl;
64 std::cerr << "Supported options:" << std::endl << std::endl;
65 std::cerr << paParser.GetHelpString() << std::endl;
66 }
67
Disassemble(const Options & options)68 static void Disassemble(const Options &options)
69 {
70 auto inputFile = options.inputFile.GetValue();
71 LOG(DEBUG, DISASSEMBLER) << "[initializing disassembler]\nfile: " << inputFile << "\n";
72
73 ark::disasm::Disassembler disasm {};
74 disasm.Disassemble(inputFile, options.quiet.GetValue(), options.skipStrings.GetValue());
75 auto verbose = options.verbose.GetValue();
76 if (verbose) {
77 auto profile = options.profile.GetValue();
78 if (!profile.empty()) {
79 disasm.SetProfile(profile);
80 }
81 disasm.CollectInfo();
82 }
83
84 LOG(DEBUG, DISASSEMBLER) << "[serializing results]\n";
85
86 std::ofstream resPa;
87 resPa.open(options.outputFile.GetValue(), std::ios::trunc | std::ios::out);
88 disasm.Serialize(resPa, options.withSeparators.GetValue(), verbose);
89 resPa.close();
90 }
91
ProcessArgs(ark::PandArgParser & paParser,const Options & options,int argc,const char ** argv)92 static bool ProcessArgs(ark::PandArgParser &paParser, const Options &options, int argc, const char **argv)
93 {
94 if (!paParser.Parse(argc, argv)) {
95 PrintHelp(paParser);
96 return false;
97 }
98
99 if (options.version.GetValue()) {
100 ark::PrintPandaVersion();
101 ark::panda_file::PrintBytecodeVersion();
102 return false;
103 }
104
105 if (options.inputFile.GetValue().empty() || options.outputFile.GetValue().empty() || options.help.GetValue()) {
106 PrintHelp(paParser);
107 return false;
108 }
109
110 if (options.debug.GetValue()) {
111 auto debugFile = options.debugFile.GetValue();
112 if (debugFile.empty()) {
113 ark::Logger::InitializeStdLogging(ark::Logger::Level::DEBUG,
114 ark::Logger::ComponentMask().set(ark::Logger::Component::DISASSEMBLER));
115 } else {
116 ark::Logger::InitializeFileLogging(debugFile, ark::Logger::Level::DEBUG,
117 ark::Logger::ComponentMask().set(ark::Logger::Component::DISASSEMBLER));
118 }
119 } else {
120 ark::Logger::InitializeStdLogging(ark::Logger::Level::ERROR,
121 ark::Logger::ComponentMask().set(ark::Logger::Component::DISASSEMBLER));
122 }
123
124 return true;
125 }
126
main(int argc,const char ** argv)127 int main(int argc, const char **argv)
128 {
129 ark::PandArgParser paParser;
130 Options options {paParser};
131
132 if (!ProcessArgs(paParser, options, argc, argv)) {
133 return 1;
134 }
135
136 Disassemble(options);
137
138 paParser.DisableTail();
139
140 return 0;
141 }
142