blob: fe546fe9cc92ea93f0ff9997973afc9f069a888a [file] [log] [blame]
Makoto Onuki8558e9a2023-08-31 10:48:38 -07001#!/bin/bash
2# Copyright (C) 2023 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16set -e
17
18
19help() {
20 cat <<'EOF'
21
22 dump-jar: Dump java classes in jar files
23
24 Usage:
25 dump-jar [-v] CLASS-FILE [...]
26
27 Dump a *.class file
28
29 dump-jar [-v] [-s] [-o OUTPUT-FILENAME] JAR-FILE[: filename regex] [...]
30
31 Dump a jar file.
32
33 If a filename contains a ':', then the following part
34 will be used to filter files in the jar file.
35
36 For example, "file.jar:/MyClass$" will only dump "MyClass" in file.jar.
37
38 Options:
39 -v: Enable verbose output.
40
41 -s: Simple output mode, used to check HostStubGen output jars.
42
43 -o: Write the output to a specified file.
44EOF
45}
46
47# Parse the options.
48
49verbose=0
50simple=0
51output=""
52while getopts "hvso:" opt; do
53case "$opt" in
54 h)
55 help
56 exit 0
57 ;;
58 v)
59 verbose=1
60 ;;
61 s)
62 simple=1
63 ;;
64 o)
65 output="$OPTARG"
66 ;;
67 '?')
68 help
69 exit 1
70 ;;
71esac
72done
73shift $(($OPTIND - 1))
74
75JAVAP_OPTS="${JAVAP_OPTS:--v -p -s -sysinfo -constants}"
76
77if (( $simple )) ; then
78 JAVAP_OPTS="-p -c -v"
79fi
80
81
82# Normalize a java class name.
83# Convert '.' to '/'
84# Remove the *.class suffix.
85normalize() {
86 local name="$1"
87 name="${name%.class}" # Remove the .class suffix.
88 echo "$name" | tr '.' '/'
89}
90
91# Convert the output for `-s` as needed.
92filter_output() {
93 if (( $simple )) ; then
94 # For "simple output" mode,
95 # - Normalize the constant numbers (replace with "#x")
Makoto Onuki6b475972023-09-22 14:50:12 -070096 # - Normalize byte code offsets and other similar numbers. (e.g. "0:" -> "x:")
Makoto Onuki8558e9a2023-08-31 10:48:38 -070097 # - Remove the constant pool
98 # - Remove the line number table
99 # - Some other transient lines
Makoto Onuki491caff2024-08-02 10:47:55 -0700100 # - Sometimes the javap shows mysterious warnings, so remove them too.
Makoto Onuki8558e9a2023-08-31 10:48:38 -0700101 #
102 # `/PATTERN-1/,/PATTERN-1/{//!d}` is a trick to delete lines between two patterns, without
103 # the start and the end lines.
104 sed -e 's/#[0-9][0-9]*/#x/g' \
Makoto Onuki6b475972023-09-22 14:50:12 -0700105 -e 's/^\( *\)[0-9][0-9]*:/\1x:/' \
Makoto Onuki8558e9a2023-08-31 10:48:38 -0700106 -e '/^Constant pool:/,/^[^ ]/{//!d}' \
107 -e '/^ *line *[0-9][0-9]*: *[0-9][0-9]*$/d' \
108 -e '/SHA-256 checksum/d' \
109 -e '/Last modified/d' \
Makoto Onuki491caff2024-08-02 10:47:55 -0700110 -e '/^Classfile jar/d' \
111 -e '/\[warning\]/d'
Makoto Onuki8558e9a2023-08-31 10:48:38 -0700112 else
113 cat # Print as-is.
114 fi
115}
116
117# Write to the output file (specified with -o) as needed.
118write_to_out() {
119 if [[ -n "$output" ]] ; then
120 cat >"$output"
121 echo "Wrote output to $output" 1>&2
122 else
123 cat # print to stdout
124 fi
125}
126
127for file in "${@}"; do
128
129 # *.class?
130 if echo "$file" | grep -qE '\.class$' ; then
131 echo "# Class: $file" 1>&2
132 javap $dump_code_opt $JAVAP_OPTS $file
133
134 # *.jar?
135 elif echo "$file" | grep -qE '\.jar(:.*)?$' ; then
136 # Take the regex. Remove everything up to : in $file
137 regex=""
138 if [[ "$file" =~ : ]] ; then
139 regex="$(normalize "${file##*:}")"
140 fi
141
142 # Remove everything after ':', inclusively, in $file.
143 file="${file%:*}"
144
145 # Print the filename and the regex.
146 if ! (( $simple )) ; then
147 echo -n "# Jar: $file"
148 if [[ "$regex" != "" ]] ;then
149 echo -n " (regex: $regex)"
150 fi
151 echo
152 fi
153
154 jar tf "$file" | grep '\.class$' | sort | while read -r class ; do
155 if normalize "$class" | grep -q -- "$regex" ; then
156 echo "## Class: $class"
157 javap $dump_code_opt $JAVAP_OPTS -cp $file ${class%.class}
158 else
159 (( $verbose )) && echo "## Skipping class: $class"
160 fi
161 done
162
163 else
164 echo "Unknown file type: $file" 1>&2
165 exit 1
166 fi
167done | filter_output | write_to_out