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 panda::Logger::ComponentMask log_mask = panda::Logger::ComponentMask().set(panda::Logger::Component::DISASSEMBLER)
72 .set(panda::Logger::Component::PANDAFILE);
73 if (debug.GetValue()) {
74 if (debug_file.GetValue().empty()) {
75 panda::Logger::InitializeStdLogging(
76 panda::Logger::Level::DEBUG, log_mask);
77 } else {
78 panda::Logger::InitializeFileLogging(
79 debug_file.GetValue(), panda::Logger::Level::DEBUG, log_mask);
80 }
81 } else {
82 panda::Logger::InitializeStdLogging(panda::Logger::Level::ERROR, log_mask);
83 }
84
85 return true;
86 }
87
main(int argc,const char ** argv)88 int main(int argc, const char **argv)
89 {
90 panda::PandArg<bool> help("help", false, "Print this message and exit");
91 panda::PandArg<bool> verbose("verbose", false, "enable informative code output");
92 panda::PandArg<bool> quiet("quiet", false, "enables all of the --skip-* flags");
93 panda::PandArg<bool> skip_strings(
94 "skip-string-literals", false,
95 "replaces string literals with their respectie id's, thus shortening emitted code size");
96 panda::PandArg<bool> debug(
97 "debug", false, "enable debug messages (will be printed to standard output if no --debug-file was specified) ");
98 panda::PandArg<std::string> debug_file("debug-file", "",
99 "(--debug-file FILENAME) set debug file name. default is std::cout");
100 panda::PandArg<std::string> input_file("input_file", "", "Path to the source binary code");
101 panda::PandArg<std::string> output_file("output_file", "", "Path to the generated assembly code");
102 panda::PandArg<bool> version {"version", false,
103 "Ark version, file format version and minimum supported file format version"};
104
105 panda::PandArgParser pa_parser;
106
107 pa_parser.Add(&help);
108 pa_parser.Add(&verbose);
109 pa_parser.Add(&quiet);
110 pa_parser.Add(&skip_strings);
111 pa_parser.Add(&debug);
112 pa_parser.Add(&debug_file);
113 pa_parser.Add(&version);
114 pa_parser.PushBackTail(&input_file);
115 pa_parser.PushBackTail(&output_file);
116 pa_parser.EnableTail();
117
118 if (!ProcessArgs(pa_parser, input_file, output_file, debug, debug_file, help, version, argc, argv)) {
119 return 1;
120 }
121
122 Disassemble(input_file.GetValue(), output_file.GetValue(), verbose.GetValue(), quiet.GetValue(),
123 skip_strings.GetValue());
124
125 pa_parser.DisableTail();
126
127 return 0;
128 }
129