{"id":484,"date":"2018-01-15T20:10:19","date_gmt":"2018-01-16T01:10:19","guid":{"rendered":"http:\/\/jebware.com\/blog\/?p=484"},"modified":"2018-01-16T11:13:53","modified_gmt":"2018-01-16T16:13:53","slug":"reading-proguards-outputs","status":"publish","type":"post","link":"https:\/\/jebware.com\/blog\/?p=484","title":{"rendered":"Reading ProGuard\u2019s Outputs"},"content":{"rendered":"<p><span style=\"font-weight: 400;\">When ProGuard processes an Android app, it generates a few output files to show what happened in each step. These files can be really helpful if you&#8217;re trying to figure out what ProGuard changed, or why your code ended up the way it did. But those files aren&#8217;t self-documenting, so I&#8217;m going to walk you through why each of those files is created and what it shows you.<\/span><\/p>\n<p><a href=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2018\/01\/files-listing.png\"><img loading=\"lazy\" class=\"size-full wp-image-486 aligncenter\" src=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2018\/01\/files-listing.png\" alt=\"\" width=\"215\" height=\"112\" \/><\/a><\/p>\n<p>These files are in the build directory, something like:<\/p>\n<pre>app\/build\/outputs\/mapping\/{buildType}\/<\/pre>\n<p><span style=\"font-weight: 400;\">Here&#8217;s a diagram I made with a really high-level overview of the steps ProGuard takes when it\u2019s analyzing your app, because the output files line up nicely with these steps.\u00a0 Refer back to this for some context around the following steps.<\/span><\/p>\n<p><a href=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2018\/01\/proguard-steps.png\"><img loading=\"lazy\" class=\"aligncenter size-full wp-image-487\" src=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2018\/01\/proguard-steps.png\" alt=\"\" width=\"1894\" height=\"985\" \/><\/a><\/p>\n<h3><span style=\"font-weight: 400;\">seeds.txt<\/span><\/h3>\n<p><span style=\"font-weight: 400;\">The first things ProGuard does is to read all of your configuration files, and then read in all of the Java bytecode (.class files) to create what it calls the <\/span><i><span style=\"font-weight: 400;\">class pool<\/span><\/i><span style=\"font-weight: 400;\">. \u00a0ProGuard then looks through the class pool and prints to <\/span><b>seeds.txt<\/b><span style=\"font-weight: 400;\"> a list of every class and member that matches any of your keep rules. \u00a0This is useful for debugging if the keep rule you wrote actually matches the class you\u2019re trying to keep.<\/span><\/p>\n<p><a href=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2018\/01\/seeds.png\"><img loading=\"lazy\" class=\"aligncenter size-full wp-image-488\" src=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2018\/01\/seeds.png\" alt=\"\" width=\"500\" height=\"95\" \/><\/a><\/p>\n<p><span style=\"font-weight: 400;\">If it\u2019s a class that matches, there will be a line with just the fully-qualified name of the class. \u00a0For a member, it will be the fully-qualified class name, followed by a colon, followed by the member\u2019s signature.<\/span><\/p>\n<h3><span style=\"font-weight: 400;\">usage.txt<\/span><\/h3>\n<p><span style=\"font-weight: 400;\">Knowing what code it has to keep, ProGuard then goes through the class pool and finds code that it <\/span><i><span style=\"font-weight: 400;\">doesn\u2019t<\/span><\/i><span style=\"font-weight: 400;\"> need to keep. \u00a0This is the shrinking phase, where ProGuard strips out unused code from the app. \u00a0As it\u2019s doing this, it prints out <\/span><b><i>unused<\/i><\/b><span style=\"font-weight: 400;\"> code &#8212; code that\u2019s being removed &#8212; to usage.txt. \u00a0Now this name seems backwards to me; I think it should be unused.txt or shrinkage.txt or something, but that\u2019s just me. \u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">This is useful if you\u2019re trying to figure out why a class doesn\u2019t exist at runtime. \u00a0You can check whether it got removed here, or got renamed in the next step.<\/span><\/p>\n<p><a href=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2018\/01\/usage.png\"><img loading=\"lazy\" class=\"aligncenter size-full wp-image-489\" src=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2018\/01\/usage.png\" alt=\"\" width=\"438\" height=\"78\" \/><\/a><\/p>\n<p><span style=\"font-weight: 400;\">If an entire class is removed, you\u2019ll get a line with the fully-qualified class name. \u00a0If only certain members of a class are removed, you get the class name followed by a colon, and then a line (indented with four spaces) for each member that was removed.<\/span><\/p>\n<h3><span style=\"font-weight: 400;\">mapping.txt<\/span><\/h3>\n<p><span style=\"font-weight: 400;\">The next thing ProGuard needs to do is obfuscate as much code as possible &#8212; that is, it\u2019s going to rename classes and members to meaningless names like \u201ca\u201d, \u201cb\u201d, etc. \u00a0As it\u2019s doing this, ProGuard prints the old name and new name for every class and member to mapping.txt. \u00a0Not all code is renamed, but all code is listed in mapping.txt.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">This is the file you need if you\u2019re trying to de-obfuscate a stacktrace. \u00a0It allows you to work backwards from the obfuscated names to the original names of code.<\/span><\/p>\n<p><a href=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2018\/01\/mapping.png\"><img loading=\"lazy\" class=\"aligncenter size-full wp-image-490\" src=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2018\/01\/mapping.png\" alt=\"\" width=\"696\" height=\"153\" \/><\/a><\/p>\n<p><span style=\"font-weight: 400;\">Each line is of the form \u201c{old name} -&gt; {new name}\u201d. \u00a0You get a line for the class name, then a line for each member of the class. \u00a0Note that constructors are shown as \u201c&lt;init&gt;()\u201d. \u00a0<\/span><\/p>\n<h3><span style=\"font-weight: 400;\">dump.txt<\/span><\/h3>\n<p><span style=\"font-weight: 400;\">After ProGuard has done all of its magic (shrinking and obfuscating), it prints out one last file which is essentially a full listing of all the code after processing. \u00a0That is, everything that\u2019s left in the class files, but in a less optimized format, so it\u2019s a <\/span><i><span style=\"font-weight: 400;\">huge<\/span><\/i><span style=\"font-weight: 400;\"> file. \u00a0I have a demo app that I use for testing ProGuard stuff, and the final app is about 1 MB, but the dump.txt is almost 18 MB. \u00a0It\u2019s <\/span><i><span style=\"font-weight: 400;\">enormous.<\/span><\/i><span style=\"font-weight: 400;\"> Here&#8217;s the output for a trivial class:<\/span><\/p>\n<p><a href=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2018\/01\/dump.png\"><img loading=\"lazy\" class=\"aligncenter wp-image-491\" src=\"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2018\/01\/dump.png\" alt=\"\" width=\"249\" height=\"290\" \/><\/a><\/p>\n<p><span style=\"font-weight: 400;\">This can be really useful, though, if you want to see what\u2019s in your class files but don\u2019t want to decompile the .class or .dex files.<\/span><\/p>\n<h2><span style=\"font-weight: 400;\">Archiving<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">One last note is that these files are important artifacts of your build &#8212; especially mapping.txt. \u00a0If this is a build you\u2019re going to distribute (say on the Play Store, or even internally for testing), you\u2019re going to need your mapping.txt to de-obfuscate stacktraces. \u00a0<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>When ProGuard processes an Android app, it generates a few output files to show what happened in each step. These files can be really helpful if you&#8217;re trying to figure out what ProGuard changed, or why your code ended up the way it did. But those files aren&#8217;t self-documenting, so I&#8217;m going to walk you &hellip; <a href=\"https:\/\/jebware.com\/blog\/?p=484\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Reading ProGuard\u2019s Outputs&#8221;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_mi_skip_tracking":false,"twitterCardType":"summary_large_image","cardImageID":0,"cardImage":"http:\/\/jebware.com\/blog\/wp-content\/uploads\/2018\/01\/proguard-steps.png","cardTitle":"","cardDesc":"","cardImageAlt":"","cardPlayer":"","cardPlayerWidth":0,"cardPlayerHeight":0,"cardPlayerStream":"","cardPlayerCodec":""},"categories":[4,16],"tags":[],"_links":{"self":[{"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/484"}],"collection":[{"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=484"}],"version-history":[{"count":4,"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/484\/revisions"}],"predecessor-version":[{"id":494,"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/484\/revisions\/494"}],"wp:attachment":[{"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=484"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=484"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jebware.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=484"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}