• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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