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