1 /*
2 * Copyright (c) 2021-2022 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
PrintHelp(panda::PandArgParser & pa_parser)23 void PrintHelp(panda::PandArgParser &pa_parser)
24 {
25 std::cerr << "Usage:" << std::endl;
26 std::cerr << "ark_disasm [options] input_file output_file" << std::endl << std::endl;
27 std::cerr << "Supported options:" << std::endl << std::endl;
28 std::cerr << pa_parser.GetHelpString() << std::endl;
29 }
30
Disassemble(const std::string & input_file,const std::string & output_file,const bool verbose,const bool quiet,const bool skip_strings)31 void Disassemble(const std::string &input_file, const std::string &output_file, const bool verbose, const bool quiet,
32 const bool skip_strings)
33 {
34 LOG(DEBUG, DISASSEMBLER) << "[initializing disassembler]\nfile: " << input_file << "\n";
35
36 panda::disasm::Disassembler disasm {};
37 disasm.Disassemble(input_file, quiet, skip_strings);
38 if (verbose) {
39 disasm.CollectInfo();
40 }
41
42 LOG(DEBUG, DISASSEMBLER) << "[serializing results]\n";
43
44 std::ofstream res_pa;
45 res_pa.open(output_file, std::ios::trunc | std::ios::out);
46 disasm.Serialize(res_pa, true, verbose);
47 res_pa.close();
48 }
49
ProcessArgs(panda::PandArgParser & pa_parser,const panda::PandArg<std::string> & input_file,const panda::PandArg<std::string> & output_file,panda::PandArg<bool> & debug,const panda::PandArg<std::string> & debug_file,const panda::PandArg<bool> & help,const panda::PandArg<bool> & version,int argc,const char ** argv)50 bool ProcessArgs(panda::PandArgParser &pa_parser, const panda::PandArg<std::string> &input_file,
51 const panda::PandArg<std::string> &output_file, panda::PandArg<bool> &debug,
52 const panda::PandArg<std::string> &debug_file, const panda::PandArg<bool> &help,
53 const panda::PandArg<bool> &version, int argc, const char **argv)
54 {
55 if (!pa_parser.Parse(argc, argv)) {
56 PrintHelp(pa_parser);
57 return false;
58 }
59
60 if (version.GetValue()) {
61 panda::PrintPandaVersion();
62 panda::panda_file::PrintBytecodeVersion();
63 return false;
64 }
65
66 if (input_file.GetValue().empty() || output_file.GetValue().empty() || help.GetValue()) {
67 PrintHelp(pa_parser);
68 return false;
69 }
70
71 if (debug.GetValue()) {
72 if (debug_file.GetValue().empty()) {
73 panda::Logger::InitializeStdLogging(
74 panda::Logger::Level::DEBUG,
75 panda::Logger::ComponentMask().set(panda::Logger::Component::DISASSEMBLER));
76 } else {
77 panda::Logger::InitializeFileLogging(
78 debug_file.GetValue(), panda::Logger::Level::DEBUG,
79 panda::Logger::ComponentMask().set(panda::Logger::Component::DISASSEMBLER));
80 }
81 } else {
82 panda::Logger::InitializeStdLogging(panda::Logger::Level::ERROR,
83 panda::Logger::ComponentMask().set(panda::Logger::Component::DISASSEMBLER));
84 }
85
86 return true;
87 }
88
main(int argc,const char ** argv)89 int main(int argc, const char **argv)
90 {
91 panda::PandArg<bool> help("help", false, "Print this message and exit");
92 panda::PandArg<bool> verbose("verbose", false, "enable informative code output");
93 panda::PandArg<bool> quiet("quiet", false, "enables all of the --skip-* flags");
94 panda::PandArg<bool> skip_strings(
95 "skip-string-literals", false,
96 "replaces string literals with their respectie id's, thus shortening emitted code size");
97 panda::PandArg<bool> debug(
98 "debug", false, "enable debug messages (will be printed to standard output if no --debug-file was specified) ");
99 panda::PandArg<std::string> debug_file("debug-file", "",
100 "(--debug-file FILENAME) set debug file name. default is std::cout");
101 panda::PandArg<std::string> input_file("input_file", "", "Path to the source binary code");
102 panda::PandArg<std::string> output_file("output_file", "", "Path to the generated assembly code");
103 panda::PandArg<bool> version {"version", false,
104 "Ark version, file format version and minimum supported file format version"};
105
106 panda::PandArgParser pa_parser;
107
108 pa_parser.Add(&help);
109 pa_parser.Add(&verbose);
110 pa_parser.Add(&quiet);
111 pa_parser.Add(&skip_strings);
112 pa_parser.Add(&debug);
113 pa_parser.Add(&debug_file);
114 pa_parser.Add(&version);
115 pa_parser.PushBackTail(&input_file);
116 pa_parser.PushBackTail(&output_file);
117 pa_parser.EnableTail();
118
119 if (!ProcessArgs(pa_parser, input_file, output_file, debug, debug_file, help, version, argc, argv)) {
120 return 1;
121 }
122
123 Disassemble(input_file.GetValue(), output_file.GetValue(), verbose.GetValue(), quiet.GetValue(),
124 skip_strings.GetValue());
125
126 pa_parser.DisableTail();
127
128 return 0;
129 }
130