1 /*
2 * Copyright (c) 2021-2023 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 panda::PandArg<bool> help {"help", false, "Print this message and exit"};
26 panda::PandArg<bool> verbose {"verbose", false, "enable informative code output"};
27 panda::PandArg<bool> quiet {"quiet", false, "enables all of the --skip-* flags"};
28 panda::PandArg<bool> skipStrings {
29 "skip-string-literals", false,
30 "replaces string literals with their respectie id's, thus shortening emitted code size"};
31 panda::PandArg<bool> withSeparators {"with_separators", false,
32 "adds comments that separate sections in the output file"};
33 panda::PandArg<bool> debug {
34 "debug", false, "enable debug messages (will be printed to standard output if no --debug-file was specified) "};
35 panda::PandArg<std::string> debugFile {"debug-file", "",
36 "(--debug-file FILENAME) set debug file name. default is std::cout"};
37 panda::PandArg<std::string> inputFile {"input_file", "", "Path to the source binary code"};
38 panda::PandArg<std::string> outputFile {"output_file", "", "Path to the generated assembly code"};
39 panda::PandArg<std::string> profile {"profile", "", "Path to the profile"};
40 panda::PandArg<bool> version {"version", false,
41 "Ark version, file format version and minimum supported file format version"};
42
OptionsOptions43 explicit Options(panda::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(panda::PandArgParser & paParser)60 void PrintHelp(panda::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 void Disassemble(const Options &options)
69 {
70 auto inputFile = options.inputFile.GetValue();
71 LOG(DEBUG, DISASSEMBLER) << "[initializing disassembler]\nfile: " << inputFile << "\n";
72
73 panda::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(panda::PandArgParser & paParser,const Options & options,int argc,const char ** argv)92 bool ProcessArgs(panda::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 panda::PrintPandaVersion();
101 panda::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 panda::Logger::InitializeStdLogging(
114 panda::Logger::Level::DEBUG,
115 panda::Logger::ComponentMask().set(panda::Logger::Component::DISASSEMBLER));
116 } else {
117 panda::Logger::InitializeFileLogging(
118 debugFile, panda::Logger::Level::DEBUG,
119 panda::Logger::ComponentMask().set(panda::Logger::Component::DISASSEMBLER));
120 }
121 } else {
122 panda::Logger::InitializeStdLogging(panda::Logger::Level::ERROR,
123 panda::Logger::ComponentMask().set(panda::Logger::Component::DISASSEMBLER));
124 }
125
126 return true;
127 }
128
main(int argc,const char ** argv)129 int main(int argc, const char **argv)
130 {
131 panda::PandArgParser paParser;
132 Options options {paParser};
133
134 if (!ProcessArgs(paParser, options, argc, argv)) {
135 return 1;
136 }
137
138 Disassemble(options);
139
140 paParser.DisableTail();
141
142 return 0;
143 }
144