1 /*
2  * Copyright (C) 2008 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  */
16 
17 /*
18  * Preparation and completion of hprof data generation.  The output is
19  * written into two files and then combined.  This is necessary because
20  * we generate some of the data (strings and classes) while we dump the
21  * heap, and some analysis tools require that the class and string data
22  * appear first.
23  */
24 
25 #include "hprof.h"
26 
27 #include <cutils/open_memstream.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <sys/time.h>
33 #include <sys/uio.h>
34 #include <time.h>
35 #include <time.h>
36 #include <unistd.h>
37 
38 #include <set>
39 
40 #include "base/logging.h"
41 #include "base/stringprintf.h"
42 #include "base/unix_file/fd_file.h"
43 #include "class_linker.h"
44 #include "common_throws.h"
45 #include "debugger.h"
46 #include "dex_file-inl.h"
47 #include "gc_root.h"
48 #include "gc/accounting/heap_bitmap.h"
49 #include "gc/heap.h"
50 #include "gc/space/space.h"
51 #include "globals.h"
52 #include "mirror/art_field-inl.h"
53 #include "mirror/class.h"
54 #include "mirror/class-inl.h"
55 #include "mirror/object-inl.h"
56 #include "os.h"
57 #include "safe_map.h"
58 #include "scoped_thread_state_change.h"
59 #include "thread_list.h"
60 
61 namespace art {
62 
63 namespace hprof {
64 
65 #define UNIQUE_ERROR -((((uintptr_t)__func__) << 16 | __LINE__) & (0x7fffffff))
66 
67 #define HPROF_TIME 0
68 #define HPROF_NULL_STACK_TRACE   0
69 #define HPROF_NULL_THREAD        0
70 
71 #define U2_TO_BUF_BE(buf, offset, value) \
72     do { \
73       unsigned char* buf_ = (unsigned char*)(buf); \
74       int offset_ = static_cast<int>(offset); \
75       uint16_t value_ = (uint16_t)(value); \
76       buf_[offset_ + 0] = (unsigned char)(value_ >>  8); \
77       buf_[offset_ + 1] = (unsigned char)(value_      ); \
78     } while (0)
79 
80 #define U4_TO_BUF_BE(buf, offset, value) \
81     do { \
82       unsigned char* buf_ = (unsigned char*)(buf); \
83       int offset_ = static_cast<int>(offset); \
84       uint32_t value_ = (uint32_t)(value); \
85       buf_[offset_ + 0] = (unsigned char)(value_ >> 24); \
86       buf_[offset_ + 1] = (unsigned char)(value_ >> 16); \
87       buf_[offset_ + 2] = (unsigned char)(value_ >>  8); \
88       buf_[offset_ + 3] = (unsigned char)(value_      ); \
89     } while (0)
90 
91 #define U8_TO_BUF_BE(buf, offset, value) \
92     do { \
93       unsigned char* buf_ = (unsigned char*)(buf); \
94       int offset_ = static_cast<int>(offset); \
95       uint64_t value_ = (uint64_t)(value); \
96       buf_[offset_ + 0] = (unsigned char)(value_ >> 56); \
97       buf_[offset_ + 1] = (unsigned char)(value_ >> 48); \
98       buf_[offset_ + 2] = (unsigned char)(value_ >> 40); \
99       buf_[offset_ + 3] = (unsigned char)(value_ >> 32); \
100       buf_[offset_ + 4] = (unsigned char)(value_ >> 24); \
101       buf_[offset_ + 5] = (unsigned char)(value_ >> 16); \
102       buf_[offset_ + 6] = (unsigned char)(value_ >>  8); \
103       buf_[offset_ + 7] = (unsigned char)(value_      ); \
104     } while (0)
105 
106 enum HprofTag {
107   HPROF_TAG_STRING = 0x01,
108   HPROF_TAG_LOAD_CLASS = 0x02,
109   HPROF_TAG_UNLOAD_CLASS = 0x03,
110   HPROF_TAG_STACK_FRAME = 0x04,
111   HPROF_TAG_STACK_TRACE = 0x05,
112   HPROF_TAG_ALLOC_SITES = 0x06,
113   HPROF_TAG_HEAP_SUMMARY = 0x07,
114   HPROF_TAG_START_THREAD = 0x0A,
115   HPROF_TAG_END_THREAD = 0x0B,
116   HPROF_TAG_HEAP_DUMP = 0x0C,
117   HPROF_TAG_HEAP_DUMP_SEGMENT = 0x1C,
118   HPROF_TAG_HEAP_DUMP_END = 0x2C,
119   HPROF_TAG_CPU_SAMPLES = 0x0D,
120   HPROF_TAG_CONTROL_SETTINGS = 0x0E,
121 };
122 
123 // Values for the first byte of HEAP_DUMP and HEAP_DUMP_SEGMENT records:
124 enum HprofHeapTag {
125   // Traditional.
126   HPROF_ROOT_UNKNOWN = 0xFF,
127   HPROF_ROOT_JNI_GLOBAL = 0x01,
128   HPROF_ROOT_JNI_LOCAL = 0x02,
129   HPROF_ROOT_JAVA_FRAME = 0x03,
130   HPROF_ROOT_NATIVE_STACK = 0x04,
131   HPROF_ROOT_STICKY_CLASS = 0x05,
132   HPROF_ROOT_THREAD_BLOCK = 0x06,
133   HPROF_ROOT_MONITOR_USED = 0x07,
134   HPROF_ROOT_THREAD_OBJECT = 0x08,
135   HPROF_CLASS_DUMP = 0x20,
136   HPROF_INSTANCE_DUMP = 0x21,
137   HPROF_OBJECT_ARRAY_DUMP = 0x22,
138   HPROF_PRIMITIVE_ARRAY_DUMP = 0x23,
139 
140   // Android.
141   HPROF_HEAP_DUMP_INFO = 0xfe,
142   HPROF_ROOT_INTERNED_STRING = 0x89,
143   HPROF_ROOT_FINALIZING = 0x8a,  // Obsolete.
144   HPROF_ROOT_DEBUGGER = 0x8b,
145   HPROF_ROOT_REFERENCE_CLEANUP = 0x8c,  // Obsolete.
146   HPROF_ROOT_VM_INTERNAL = 0x8d,
147   HPROF_ROOT_JNI_MONITOR = 0x8e,
148   HPROF_UNREACHABLE = 0x90,  // Obsolete.
149   HPROF_PRIMITIVE_ARRAY_NODATA_DUMP = 0xc3,  // Obsolete.
150 };
151 
152 enum HprofHeapId {
153   HPROF_HEAP_DEFAULT = 0,
154   HPROF_HEAP_ZYGOTE = 'Z',
155   HPROF_HEAP_APP = 'A',
156   HPROF_HEAP_IMAGE = 'I',
157 };
158 
159 enum HprofBasicType {
160   hprof_basic_object = 2,
161   hprof_basic_boolean = 4,
162   hprof_basic_char = 5,
163   hprof_basic_float = 6,
164   hprof_basic_double = 7,
165   hprof_basic_byte = 8,
166   hprof_basic_short = 9,
167   hprof_basic_int = 10,
168   hprof_basic_long = 11,
169 };
170 
171 typedef uint32_t HprofStringId;
172 typedef uint32_t HprofClassObjectId;
173 
174 // Represents a top-level hprof record, whose serialized format is:
175 // U1  TAG: denoting the type of the record
176 // U4  TIME: number of microseconds since the time stamp in the header
177 // U4  LENGTH: number of bytes that follow this uint32_t field and belong to this record
178 // U1* BODY: as many bytes as specified in the above uint32_t field
179 class HprofRecord {
180  public:
HprofRecord()181   HprofRecord() : alloc_length_(128), fp_(nullptr), tag_(0), time_(0), length_(0), dirty_(false) {
182     body_ = reinterpret_cast<unsigned char*>(malloc(alloc_length_));
183   }
184 
~HprofRecord()185   ~HprofRecord() {
186     free(body_);
187   }
188 
StartNewRecord(FILE * fp,uint8_t tag,uint32_t time)189   int StartNewRecord(FILE* fp, uint8_t tag, uint32_t time) {
190     int rc = Flush();
191     if (rc != 0) {
192       return rc;
193     }
194 
195     fp_ = fp;
196     tag_ = tag;
197     time_ = time;
198     length_ = 0;
199     dirty_ = true;
200     return 0;
201   }
202 
Flush()203   int Flush() {
204     if (dirty_) {
205       unsigned char headBuf[sizeof(uint8_t) + 2 * sizeof(uint32_t)];
206 
207       headBuf[0] = tag_;
208       U4_TO_BUF_BE(headBuf, 1, time_);
209       U4_TO_BUF_BE(headBuf, 5, length_);
210 
211       int nb = fwrite(headBuf, 1, sizeof(headBuf), fp_);
212       if (nb != sizeof(headBuf)) {
213         return UNIQUE_ERROR;
214       }
215       nb = fwrite(body_, 1, length_, fp_);
216       if (nb != static_cast<int>(length_)) {
217         return UNIQUE_ERROR;
218       }
219 
220       dirty_ = false;
221     }
222     // TODO if we used less than half (or whatever) of allocLen, shrink the buffer.
223     return 0;
224   }
225 
AddU1(uint8_t value)226   int AddU1(uint8_t value) {
227     int err = GuaranteeRecordAppend(1);
228     if (UNLIKELY(err != 0)) {
229       return err;
230     }
231 
232     body_[length_++] = value;
233     return 0;
234   }
235 
AddU2(uint16_t value)236   int AddU2(uint16_t value) {
237     return AddU2List(&value, 1);
238   }
239 
AddU4(uint32_t value)240   int AddU4(uint32_t value) {
241     return AddU4List(&value, 1);
242   }
243 
AddU8(uint64_t value)244   int AddU8(uint64_t value) {
245     return AddU8List(&value, 1);
246   }
247 
AddObjectId(const mirror::Object * value)248   int AddObjectId(const mirror::Object* value) {
249     return AddU4(PointerToLowMemUInt32(value));
250   }
251 
252   // The ID for the synthetic object generated to account for class static overhead.
AddClassStaticsId(const mirror::Class * value)253   int AddClassStaticsId(const mirror::Class* value) {
254     return AddU4(1 | PointerToLowMemUInt32(value));
255   }
256 
AddJniGlobalRefId(jobject value)257   int AddJniGlobalRefId(jobject value) {
258     return AddU4(PointerToLowMemUInt32(value));
259   }
260 
AddClassId(HprofClassObjectId value)261   int AddClassId(HprofClassObjectId value) {
262     return AddU4(value);
263   }
264 
AddStringId(HprofStringId value)265   int AddStringId(HprofStringId value) {
266     return AddU4(value);
267   }
268 
AddU1List(const uint8_t * values,size_t numValues)269   int AddU1List(const uint8_t* values, size_t numValues) {
270     int err = GuaranteeRecordAppend(numValues);
271     if (UNLIKELY(err != 0)) {
272       return err;
273     }
274 
275     memcpy(body_ + length_, values, numValues);
276     length_ += numValues;
277     return 0;
278   }
279 
AddU2List(const uint16_t * values,size_t numValues)280   int AddU2List(const uint16_t* values, size_t numValues) {
281     int err = GuaranteeRecordAppend(numValues * 2);
282     if (UNLIKELY(err != 0)) {
283       return err;
284     }
285 
286     unsigned char* insert = body_ + length_;
287     for (size_t i = 0; i < numValues; ++i) {
288       U2_TO_BUF_BE(insert, 0, *values++);
289       insert += sizeof(*values);
290     }
291     length_ += numValues * 2;
292     return 0;
293   }
294 
AddU4List(const uint32_t * values,size_t numValues)295   int AddU4List(const uint32_t* values, size_t numValues) {
296     int err = GuaranteeRecordAppend(numValues * 4);
297     if (UNLIKELY(err != 0)) {
298       return err;
299     }
300 
301     unsigned char* insert = body_ + length_;
302     for (size_t i = 0; i < numValues; ++i) {
303       U4_TO_BUF_BE(insert, 0, *values++);
304       insert += sizeof(*values);
305     }
306     length_ += numValues * 4;
307     return 0;
308   }
309 
UpdateU4(size_t offset,uint32_t new_value)310   void UpdateU4(size_t offset, uint32_t new_value) {
311     U4_TO_BUF_BE(body_, offset, new_value);
312   }
313 
AddU8List(const uint64_t * values,size_t numValues)314   int AddU8List(const uint64_t* values, size_t numValues) {
315     int err = GuaranteeRecordAppend(numValues * 8);
316     if (err != 0) {
317       return err;
318     }
319 
320     unsigned char* insert = body_ + length_;
321     for (size_t i = 0; i < numValues; ++i) {
322       U8_TO_BUF_BE(insert, 0, *values++);
323       insert += sizeof(*values);
324     }
325     length_ += numValues * 8;
326     return 0;
327   }
328 
AddIdList(mirror::ObjectArray<mirror::Object> * values)329   int AddIdList(mirror::ObjectArray<mirror::Object>* values)
330       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
331     int32_t length = values->GetLength();
332     for (int32_t i = 0; i < length; ++i) {
333       int err = AddObjectId(values->GetWithoutChecks(i));
334       if (UNLIKELY(err != 0)) {
335         return err;
336       }
337     }
338     return 0;
339   }
340 
AddUtf8String(const char * str)341   int AddUtf8String(const char* str) {
342     // The terminating NUL character is NOT written.
343     return AddU1List((const uint8_t*)str, strlen(str));
344   }
345 
Size() const346   size_t Size() const {
347     return length_;
348   }
349 
350  private:
GuaranteeRecordAppend(size_t nmore)351   int GuaranteeRecordAppend(size_t nmore) {
352     size_t minSize = length_ + nmore;
353     if (minSize > alloc_length_) {
354       size_t newAllocLen = alloc_length_ * 2;
355       if (newAllocLen < minSize) {
356         newAllocLen = alloc_length_ + nmore + nmore/2;
357       }
358       unsigned char* newBody = (unsigned char*)realloc(body_, newAllocLen);
359       if (newBody != NULL) {
360         body_ = newBody;
361         alloc_length_ = newAllocLen;
362       } else {
363         // TODO: set an error flag so future ops will fail
364         return UNIQUE_ERROR;
365       }
366     }
367 
368     CHECK_LE(length_ + nmore, alloc_length_);
369     return 0;
370   }
371 
372   size_t alloc_length_;
373   unsigned char* body_;
374 
375   FILE* fp_;
376   uint8_t tag_;
377   uint32_t time_;
378   size_t length_;
379   bool dirty_;
380 
381   DISALLOW_COPY_AND_ASSIGN(HprofRecord);
382 };
383 
384 class Hprof {
385  public:
Hprof(const char * output_filename,int fd,bool direct_to_ddms)386   Hprof(const char* output_filename, int fd, bool direct_to_ddms)
387       : filename_(output_filename),
388         fd_(fd),
389         direct_to_ddms_(direct_to_ddms),
390         start_ns_(NanoTime()),
391         current_record_(),
392         gc_thread_serial_number_(0),
393         gc_scan_state_(0),
394         current_heap_(HPROF_HEAP_DEFAULT),
395         objects_in_segment_(0),
396         header_fp_(NULL),
397         header_data_ptr_(NULL),
398         header_data_size_(0),
399         body_fp_(NULL),
400         body_data_ptr_(NULL),
401         body_data_size_(0),
402         next_string_id_(0x400000) {
403     LOG(INFO) << "hprof: heap dump \"" << filename_ << "\" starting...";
404 
405     header_fp_ = open_memstream(&header_data_ptr_, &header_data_size_);
406     if (header_fp_ == NULL) {
407       PLOG(FATAL) << "header open_memstream failed";
408     }
409 
410     body_fp_ = open_memstream(&body_data_ptr_, &body_data_size_);
411     if (body_fp_ == NULL) {
412       PLOG(FATAL) << "body open_memstream failed";
413     }
414   }
415 
~Hprof()416   ~Hprof() {
417     if (header_fp_ != NULL) {
418       fclose(header_fp_);
419     }
420     if (body_fp_ != NULL) {
421       fclose(body_fp_);
422     }
423     free(header_data_ptr_);
424     free(body_data_ptr_);
425   }
426 
Dump()427   void Dump()
428       EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_)
429       LOCKS_EXCLUDED(Locks::heap_bitmap_lock_) {
430     // Walk the roots and the heap.
431     current_record_.StartNewRecord(body_fp_, HPROF_TAG_HEAP_DUMP_SEGMENT, HPROF_TIME);
432     Runtime::Current()->VisitRoots(RootVisitor, this);
433     Thread* self = Thread::Current();
434     {
435       ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
436       Runtime::Current()->GetHeap()->VisitObjects(VisitObjectCallback, this);
437     }
438     current_record_.StartNewRecord(body_fp_, HPROF_TAG_HEAP_DUMP_END, HPROF_TIME);
439     current_record_.Flush();
440     fflush(body_fp_);
441 
442     // Write the header.
443     WriteFixedHeader();
444     // Write the string and class tables, and any stack traces, to the header.
445     // (jhat requires that these appear before any of the data in the body that refers to them.)
446     WriteStringTable();
447     WriteClassTable();
448     WriteStackTraces();
449     current_record_.Flush();
450     fflush(header_fp_);
451 
452     bool okay = true;
453     if (direct_to_ddms_) {
454       // Send the data off to DDMS.
455       iovec iov[2];
456       iov[0].iov_base = header_data_ptr_;
457       iov[0].iov_len = header_data_size_;
458       iov[1].iov_base = body_data_ptr_;
459       iov[1].iov_len = body_data_size_;
460       Dbg::DdmSendChunkV(CHUNK_TYPE("HPDS"), iov, 2);
461     } else {
462       // Where exactly are we writing to?
463       int out_fd;
464       if (fd_ >= 0) {
465         out_fd = dup(fd_);
466         if (out_fd < 0) {
467           ThrowRuntimeException("Couldn't dump heap; dup(%d) failed: %s", fd_, strerror(errno));
468           return;
469         }
470       } else {
471         out_fd = open(filename_.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
472         if (out_fd < 0) {
473           ThrowRuntimeException("Couldn't dump heap; open(\"%s\") failed: %s", filename_.c_str(),
474                                 strerror(errno));
475           return;
476         }
477       }
478 
479       std::unique_ptr<File> file(new File(out_fd, filename_, true));
480       okay = file->WriteFully(header_data_ptr_, header_data_size_) &&
481              file->WriteFully(body_data_ptr_, body_data_size_);
482       if (okay) {
483         okay = file->FlushCloseOrErase() == 0;
484       } else {
485         file->Erase();
486       }
487       if (!okay) {
488         std::string msg(StringPrintf("Couldn't dump heap; writing \"%s\" failed: %s",
489                                      filename_.c_str(), strerror(errno)));
490         ThrowRuntimeException("%s", msg.c_str());
491         LOG(ERROR) << msg;
492       }
493     }
494 
495     // Throw out a log message for the benefit of "runhat".
496     if (okay) {
497       uint64_t duration = NanoTime() - start_ns_;
498       LOG(INFO) << "hprof: heap dump completed ("
499           << PrettySize(header_data_size_ + body_data_size_ + 1023)
500           << ") in " << PrettyDuration(duration);
501     }
502   }
503 
504  private:
RootVisitor(mirror::Object ** obj,void * arg,const RootInfo & root_info)505   static void RootVisitor(mirror::Object** obj, void* arg, const RootInfo& root_info)
506       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
507     DCHECK(arg != nullptr);
508     DCHECK(obj != nullptr);
509     DCHECK(*obj != nullptr);
510     reinterpret_cast<Hprof*>(arg)->VisitRoot(*obj, root_info);
511   }
512 
VisitObjectCallback(mirror::Object * obj,void * arg)513   static void VisitObjectCallback(mirror::Object* obj, void* arg)
514       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
515     DCHECK(obj != NULL);
516     DCHECK(arg != NULL);
517     reinterpret_cast<Hprof*>(arg)->DumpHeapObject(obj);
518   }
519 
520   void VisitRoot(const mirror::Object* obj, const RootInfo& root_info)
521       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
522 
523   int DumpHeapObject(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
524 
Finish()525   void Finish() {
526   }
527 
WriteClassTable()528   int WriteClassTable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
529     HprofRecord* rec = &current_record_;
530     uint32_t nextSerialNumber = 1;
531 
532     for (mirror::Class* c : classes_) {
533       CHECK(c != nullptr);
534 
535       int err = current_record_.StartNewRecord(header_fp_, HPROF_TAG_LOAD_CLASS, HPROF_TIME);
536       if (UNLIKELY(err != 0)) {
537         return err;
538       }
539 
540       // LOAD CLASS format:
541       // U4: class serial number (always > 0)
542       // ID: class object ID. We use the address of the class object structure as its ID.
543       // U4: stack trace serial number
544       // ID: class name string ID
545       rec->AddU4(nextSerialNumber++);
546       rec->AddObjectId(c);
547       rec->AddU4(HPROF_NULL_STACK_TRACE);
548       rec->AddStringId(LookupClassNameId(c));
549     }
550 
551     return 0;
552   }
553 
WriteStringTable()554   int WriteStringTable() {
555     HprofRecord* rec = &current_record_;
556 
557     for (std::pair<std::string, HprofStringId> p : strings_) {
558       const std::string& string = p.first;
559       size_t id = p.second;
560 
561       int err = current_record_.StartNewRecord(header_fp_, HPROF_TAG_STRING, HPROF_TIME);
562       if (err != 0) {
563         return err;
564       }
565 
566       // STRING format:
567       // ID:  ID for this string
568       // U1*: UTF8 characters for string (NOT NULL terminated)
569       //      (the record format encodes the length)
570       err = rec->AddU4(id);
571       if (err != 0) {
572         return err;
573       }
574       err = rec->AddUtf8String(string.c_str());
575       if (err != 0) {
576         return err;
577       }
578     }
579 
580     return 0;
581   }
582 
StartNewHeapDumpSegment()583   void StartNewHeapDumpSegment() {
584     // This flushes the old segment and starts a new one.
585     current_record_.StartNewRecord(body_fp_, HPROF_TAG_HEAP_DUMP_SEGMENT, HPROF_TIME);
586     objects_in_segment_ = 0;
587 
588     // Starting a new HEAP_DUMP resets the heap to default.
589     current_heap_ = HPROF_HEAP_DEFAULT;
590   }
591 
592   int MarkRootObject(const mirror::Object* obj, jobject jniObj);
593 
LookupClassId(mirror::Class * c)594   HprofClassObjectId LookupClassId(mirror::Class* c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
595     if (c == nullptr) {
596       // c is the superclass of java.lang.Object or a primitive.
597       return 0;
598     }
599 
600     {
601       auto result = classes_.insert(c);
602       const mirror::Class* present = *result.first;
603       CHECK_EQ(present, c);
604     }
605 
606     // Make sure that we've assigned a string ID for this class' name
607     LookupClassNameId(c);
608 
609     HprofClassObjectId result = PointerToLowMemUInt32(c);
610     return result;
611   }
612 
LookupStringId(mirror::String * string)613   HprofStringId LookupStringId(mirror::String* string) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
614     return LookupStringId(string->ToModifiedUtf8());
615   }
616 
LookupStringId(const char * string)617   HprofStringId LookupStringId(const char* string) {
618     return LookupStringId(std::string(string));
619   }
620 
LookupStringId(const std::string & string)621   HprofStringId LookupStringId(const std::string& string) {
622     auto it = strings_.find(string);
623     if (it != strings_.end()) {
624       return it->second;
625     }
626     HprofStringId id = next_string_id_++;
627     strings_.Put(string, id);
628     return id;
629   }
630 
LookupClassNameId(mirror::Class * c)631   HprofStringId LookupClassNameId(mirror::Class* c) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
632     return LookupStringId(PrettyDescriptor(c));
633   }
634 
WriteFixedHeader()635   void WriteFixedHeader() {
636     char magic[] = "JAVA PROFILE 1.0.3";
637     unsigned char buf[4];
638 
639     // Write the file header.
640     // U1: NUL-terminated magic string.
641     fwrite(magic, 1, sizeof(magic), header_fp_);
642 
643     // U4: size of identifiers.  We're using addresses as IDs and our heap references are stored
644     // as uint32_t.
645     // Note of warning: hprof-conv hard-codes the size of identifiers to 4.
646     COMPILE_ASSERT(sizeof(mirror::HeapReference<mirror::Object>) == sizeof(uint32_t),
647       UnexpectedHeapReferenceSize);
648     U4_TO_BUF_BE(buf, 0, sizeof(uint32_t));
649     fwrite(buf, 1, sizeof(uint32_t), header_fp_);
650 
651     // The current time, in milliseconds since 0:00 GMT, 1/1/70.
652     timeval now;
653     uint64_t nowMs;
654     if (gettimeofday(&now, NULL) < 0) {
655       nowMs = 0;
656     } else {
657       nowMs = (uint64_t)now.tv_sec * 1000 + now.tv_usec / 1000;
658     }
659 
660     // U4: high word of the 64-bit time.
661     U4_TO_BUF_BE(buf, 0, (uint32_t)(nowMs >> 32));
662     fwrite(buf, 1, sizeof(uint32_t), header_fp_);
663 
664     // U4: low word of the 64-bit time.
665     U4_TO_BUF_BE(buf, 0, (uint32_t)(nowMs & 0xffffffffULL));
666     fwrite(buf, 1, sizeof(uint32_t), header_fp_);  // xxx fix the time
667   }
668 
WriteStackTraces()669   void WriteStackTraces() {
670     // Write a dummy stack trace record so the analysis tools don't freak out.
671     current_record_.StartNewRecord(header_fp_, HPROF_TAG_STACK_TRACE, HPROF_TIME);
672     current_record_.AddU4(HPROF_NULL_STACK_TRACE);
673     current_record_.AddU4(HPROF_NULL_THREAD);
674     current_record_.AddU4(0);    // no frames
675   }
676 
677   // If direct_to_ddms_ is set, "filename_" and "fd" will be ignored.
678   // Otherwise, "filename_" must be valid, though if "fd" >= 0 it will
679   // only be used for debug messages.
680   std::string filename_;
681   int fd_;
682   bool direct_to_ddms_;
683 
684   uint64_t start_ns_;
685 
686   HprofRecord current_record_;
687 
688   uint32_t gc_thread_serial_number_;
689   uint8_t gc_scan_state_;
690   HprofHeapId current_heap_;  // Which heap we're currently dumping.
691   size_t objects_in_segment_;
692 
693   FILE* header_fp_;
694   char* header_data_ptr_;
695   size_t header_data_size_;
696 
697   FILE* body_fp_;
698   char* body_data_ptr_;
699   size_t body_data_size_;
700 
701   std::set<mirror::Class*> classes_;
702   HprofStringId next_string_id_;
703   SafeMap<std::string, HprofStringId> strings_;
704 
705   DISALLOW_COPY_AND_ASSIGN(Hprof);
706 };
707 
708 #define OBJECTS_PER_SEGMENT     ((size_t)128)
709 #define BYTES_PER_SEGMENT       ((size_t)4096)
710 
711 // The static field-name for the synthetic object generated to account for class static overhead.
712 #define STATIC_OVERHEAD_NAME    "$staticOverhead"
713 
SignatureToBasicTypeAndSize(const char * sig,size_t * sizeOut)714 static HprofBasicType SignatureToBasicTypeAndSize(const char* sig, size_t* sizeOut) {
715   char c = sig[0];
716   HprofBasicType ret;
717   size_t size;
718 
719   switch (c) {
720   case '[':
721   case 'L': ret = hprof_basic_object;  size = 4; break;
722   case 'Z': ret = hprof_basic_boolean; size = 1; break;
723   case 'C': ret = hprof_basic_char;    size = 2; break;
724   case 'F': ret = hprof_basic_float;   size = 4; break;
725   case 'D': ret = hprof_basic_double;  size = 8; break;
726   case 'B': ret = hprof_basic_byte;    size = 1; break;
727   case 'S': ret = hprof_basic_short;   size = 2; break;
728   default: CHECK(false);
729   case 'I': ret = hprof_basic_int;     size = 4; break;
730   case 'J': ret = hprof_basic_long;    size = 8; break;
731   }
732 
733   if (sizeOut != NULL) {
734     *sizeOut = size;
735   }
736 
737   return ret;
738 }
739 
PrimitiveToBasicTypeAndSize(Primitive::Type prim,size_t * sizeOut)740 static HprofBasicType PrimitiveToBasicTypeAndSize(Primitive::Type prim, size_t* sizeOut) {
741   HprofBasicType ret;
742   size_t size;
743 
744   switch (prim) {
745   case Primitive::kPrimBoolean: ret = hprof_basic_boolean; size = 1; break;
746   case Primitive::kPrimChar:    ret = hprof_basic_char;    size = 2; break;
747   case Primitive::kPrimFloat:   ret = hprof_basic_float;   size = 4; break;
748   case Primitive::kPrimDouble:  ret = hprof_basic_double;  size = 8; break;
749   case Primitive::kPrimByte:    ret = hprof_basic_byte;    size = 1; break;
750   case Primitive::kPrimShort:   ret = hprof_basic_short;   size = 2; break;
751   default: CHECK(false);
752   case Primitive::kPrimInt:     ret = hprof_basic_int;     size = 4; break;
753   case Primitive::kPrimLong:    ret = hprof_basic_long;    size = 8; break;
754   }
755 
756   if (sizeOut != NULL) {
757     *sizeOut = size;
758   }
759 
760   return ret;
761 }
762 
763 // Always called when marking objects, but only does
764 // something when ctx->gc_scan_state_ is non-zero, which is usually
765 // only true when marking the root set or unreachable
766 // objects.  Used to add rootset references to obj.
MarkRootObject(const mirror::Object * obj,jobject jniObj)767 int Hprof::MarkRootObject(const mirror::Object* obj, jobject jniObj) {
768   HprofRecord* rec = &current_record_;
769   HprofHeapTag heapTag = (HprofHeapTag)gc_scan_state_;
770 
771   if (heapTag == 0) {
772     return 0;
773   }
774 
775   if (objects_in_segment_ >= OBJECTS_PER_SEGMENT || rec->Size() >= BYTES_PER_SEGMENT) {
776     StartNewHeapDumpSegment();
777   }
778 
779   switch (heapTag) {
780   // ID: object ID
781   case HPROF_ROOT_UNKNOWN:
782   case HPROF_ROOT_STICKY_CLASS:
783   case HPROF_ROOT_MONITOR_USED:
784   case HPROF_ROOT_INTERNED_STRING:
785   case HPROF_ROOT_DEBUGGER:
786   case HPROF_ROOT_VM_INTERNAL:
787     rec->AddU1(heapTag);
788     rec->AddObjectId(obj);
789     break;
790 
791   // ID: object ID
792   // ID: JNI global ref ID
793   case HPROF_ROOT_JNI_GLOBAL:
794     rec->AddU1(heapTag);
795     rec->AddObjectId(obj);
796     rec->AddJniGlobalRefId(jniObj);
797     break;
798 
799   // ID: object ID
800   // U4: thread serial number
801   // U4: frame number in stack trace (-1 for empty)
802   case HPROF_ROOT_JNI_LOCAL:
803   case HPROF_ROOT_JNI_MONITOR:
804   case HPROF_ROOT_JAVA_FRAME:
805     rec->AddU1(heapTag);
806     rec->AddObjectId(obj);
807     rec->AddU4(gc_thread_serial_number_);
808     rec->AddU4((uint32_t)-1);
809     break;
810 
811   // ID: object ID
812   // U4: thread serial number
813   case HPROF_ROOT_NATIVE_STACK:
814   case HPROF_ROOT_THREAD_BLOCK:
815     rec->AddU1(heapTag);
816     rec->AddObjectId(obj);
817     rec->AddU4(gc_thread_serial_number_);
818     break;
819 
820   // ID: thread object ID
821   // U4: thread serial number
822   // U4: stack trace serial number
823   case HPROF_ROOT_THREAD_OBJECT:
824     rec->AddU1(heapTag);
825     rec->AddObjectId(obj);
826     rec->AddU4(gc_thread_serial_number_);
827     rec->AddU4((uint32_t)-1);    // xxx
828     break;
829 
830   case HPROF_CLASS_DUMP:
831   case HPROF_INSTANCE_DUMP:
832   case HPROF_OBJECT_ARRAY_DUMP:
833   case HPROF_PRIMITIVE_ARRAY_DUMP:
834   case HPROF_HEAP_DUMP_INFO:
835   case HPROF_PRIMITIVE_ARRAY_NODATA_DUMP:
836     // Ignored.
837     break;
838 
839   case HPROF_ROOT_FINALIZING:
840   case HPROF_ROOT_REFERENCE_CLEANUP:
841   case HPROF_UNREACHABLE:
842     LOG(FATAL) << "obsolete tag " << static_cast<int>(heapTag);
843     break;
844   }
845 
846   ++objects_in_segment_;
847   return 0;
848 }
849 
StackTraceSerialNumber(const mirror::Object *)850 static int StackTraceSerialNumber(const mirror::Object* /*obj*/) {
851   return HPROF_NULL_STACK_TRACE;
852 }
853 
DumpHeapObject(mirror::Object * obj)854 int Hprof::DumpHeapObject(mirror::Object* obj) {
855   HprofRecord* rec = &current_record_;
856   gc::space::ContinuousSpace* space =
857       Runtime::Current()->GetHeap()->FindContinuousSpaceFromObject(obj, true);
858   HprofHeapId heap_type = HPROF_HEAP_APP;
859   if (space != nullptr) {
860     if (space->IsZygoteSpace()) {
861       heap_type = HPROF_HEAP_ZYGOTE;
862     } else if (space->IsImageSpace()) {
863       heap_type = HPROF_HEAP_IMAGE;
864     }
865   }
866   if (objects_in_segment_ >= OBJECTS_PER_SEGMENT || rec->Size() >= BYTES_PER_SEGMENT) {
867     StartNewHeapDumpSegment();
868   }
869 
870   if (heap_type != current_heap_) {
871     HprofStringId nameId;
872 
873     // This object is in a different heap than the current one.
874     // Emit a HEAP_DUMP_INFO tag to change heaps.
875     rec->AddU1(HPROF_HEAP_DUMP_INFO);
876     rec->AddU4(static_cast<uint32_t>(heap_type));   // uint32_t: heap type
877     switch (heap_type) {
878     case HPROF_HEAP_APP:
879       nameId = LookupStringId("app");
880       break;
881     case HPROF_HEAP_ZYGOTE:
882       nameId = LookupStringId("zygote");
883       break;
884     case HPROF_HEAP_IMAGE:
885       nameId = LookupStringId("image");
886       break;
887     default:
888       // Internal error
889       LOG(ERROR) << "Unexpected desiredHeap";
890       nameId = LookupStringId("<ILLEGAL>");
891       break;
892     }
893     rec->AddStringId(nameId);
894     current_heap_ = heap_type;
895   }
896 
897   mirror::Class* c = obj->GetClass();
898   if (c == NULL) {
899     // This object will bother HprofReader, because it has a NULL
900     // class, so just don't dump it. It could be
901     // gDvm.unlinkedJavaLangClass or it could be an object just
902     // allocated which hasn't been initialized yet.
903   } else {
904     if (obj->IsClass()) {
905       mirror::Class* thisClass = obj->AsClass();
906       // obj is a ClassObject.
907       size_t sFieldCount = thisClass->NumStaticFields();
908       if (sFieldCount != 0) {
909         int byteLength = sFieldCount * sizeof(JValue);  // TODO bogus; fields are packed
910         // Create a byte array to reflect the allocation of the
911         // StaticField array at the end of this class.
912         rec->AddU1(HPROF_PRIMITIVE_ARRAY_DUMP);
913         rec->AddClassStaticsId(thisClass);
914         rec->AddU4(StackTraceSerialNumber(obj));
915         rec->AddU4(byteLength);
916         rec->AddU1(hprof_basic_byte);
917         for (int i = 0; i < byteLength; ++i) {
918           rec->AddU1(0);
919         }
920       }
921 
922       rec->AddU1(HPROF_CLASS_DUMP);
923       rec->AddClassId(LookupClassId(thisClass));
924       rec->AddU4(StackTraceSerialNumber(thisClass));
925       rec->AddClassId(LookupClassId(thisClass->GetSuperClass()));
926       rec->AddObjectId(thisClass->GetClassLoader());
927       rec->AddObjectId(nullptr);    // no signer
928       rec->AddObjectId(nullptr);    // no prot domain
929       rec->AddObjectId(nullptr);    // reserved
930       rec->AddObjectId(nullptr);    // reserved
931       if (thisClass->IsClassClass()) {
932         // ClassObjects have their static fields appended, so aren't all the same size.
933         // But they're at least this size.
934         rec->AddU4(sizeof(mirror::Class));  // instance size
935       } else if (thisClass->IsArrayClass() || thisClass->IsPrimitive()) {
936         rec->AddU4(0);
937       } else {
938         rec->AddU4(thisClass->GetObjectSize());  // instance size
939       }
940 
941       rec->AddU2(0);  // empty const pool
942 
943       // Static fields
944       if (sFieldCount == 0) {
945         rec->AddU2((uint16_t)0);
946       } else {
947         rec->AddU2((uint16_t)(sFieldCount+1));
948         rec->AddStringId(LookupStringId(STATIC_OVERHEAD_NAME));
949         rec->AddU1(hprof_basic_object);
950         rec->AddClassStaticsId(thisClass);
951 
952         for (size_t i = 0; i < sFieldCount; ++i) {
953           mirror::ArtField* f = thisClass->GetStaticField(i);
954 
955           size_t size;
956           HprofBasicType t = SignatureToBasicTypeAndSize(f->GetTypeDescriptor(), &size);
957           rec->AddStringId(LookupStringId(f->GetName()));
958           rec->AddU1(t);
959           if (size == 1) {
960             rec->AddU1(static_cast<uint8_t>(f->Get32(thisClass)));
961           } else if (size == 2) {
962             rec->AddU2(static_cast<uint16_t>(f->Get32(thisClass)));
963           } else if (size == 4) {
964             rec->AddU4(f->Get32(thisClass));
965           } else if (size == 8) {
966             rec->AddU8(f->Get64(thisClass));
967           } else {
968             CHECK(false);
969           }
970         }
971       }
972 
973       // Instance fields for this class (no superclass fields)
974       int iFieldCount = thisClass->IsObjectClass() ? 0 : thisClass->NumInstanceFields();
975       rec->AddU2((uint16_t)iFieldCount);
976       for (int i = 0; i < iFieldCount; ++i) {
977         mirror::ArtField* f = thisClass->GetInstanceField(i);
978         HprofBasicType t = SignatureToBasicTypeAndSize(f->GetTypeDescriptor(), NULL);
979         rec->AddStringId(LookupStringId(f->GetName()));
980         rec->AddU1(t);
981       }
982     } else if (c->IsArrayClass()) {
983       mirror::Array* aobj = obj->AsArray();
984       uint32_t length = aobj->GetLength();
985 
986       if (obj->IsObjectArray()) {
987         // obj is an object array.
988         rec->AddU1(HPROF_OBJECT_ARRAY_DUMP);
989 
990         rec->AddObjectId(obj);
991         rec->AddU4(StackTraceSerialNumber(obj));
992         rec->AddU4(length);
993         rec->AddClassId(LookupClassId(c));
994 
995         // Dump the elements, which are always objects or NULL.
996         rec->AddIdList(aobj->AsObjectArray<mirror::Object>());
997       } else {
998         size_t size;
999         HprofBasicType t = PrimitiveToBasicTypeAndSize(c->GetComponentType()->GetPrimitiveType(), &size);
1000 
1001         // obj is a primitive array.
1002         rec->AddU1(HPROF_PRIMITIVE_ARRAY_DUMP);
1003 
1004         rec->AddObjectId(obj);
1005         rec->AddU4(StackTraceSerialNumber(obj));
1006         rec->AddU4(length);
1007         rec->AddU1(t);
1008 
1009         // Dump the raw, packed element values.
1010         if (size == 1) {
1011           rec->AddU1List((const uint8_t*)aobj->GetRawData(sizeof(uint8_t), 0), length);
1012         } else if (size == 2) {
1013           rec->AddU2List((const uint16_t*)aobj->GetRawData(sizeof(uint16_t), 0), length);
1014         } else if (size == 4) {
1015           rec->AddU4List((const uint32_t*)aobj->GetRawData(sizeof(uint32_t), 0), length);
1016         } else if (size == 8) {
1017           rec->AddU8List((const uint64_t*)aobj->GetRawData(sizeof(uint64_t), 0), length);
1018         }
1019       }
1020     } else {
1021       // obj is an instance object.
1022       rec->AddU1(HPROF_INSTANCE_DUMP);
1023       rec->AddObjectId(obj);
1024       rec->AddU4(StackTraceSerialNumber(obj));
1025       rec->AddClassId(LookupClassId(c));
1026 
1027       // Reserve some space for the length of the instance data, which we won't
1028       // know until we're done writing it.
1029       size_t size_patch_offset = rec->Size();
1030       rec->AddU4(0x77777777);
1031 
1032       // Write the instance data;  fields for this class, followed by super class fields,
1033       // and so on. Don't write the klass or monitor fields of Object.class.
1034       mirror::Class* sclass = c;
1035       while (!sclass->IsObjectClass()) {
1036         int ifieldCount = sclass->NumInstanceFields();
1037         for (int i = 0; i < ifieldCount; ++i) {
1038           mirror::ArtField* f = sclass->GetInstanceField(i);
1039           size_t size;
1040           SignatureToBasicTypeAndSize(f->GetTypeDescriptor(), &size);
1041           if (size == 1) {
1042             rec->AddU1(f->Get32(obj));
1043           } else if (size == 2) {
1044             rec->AddU2(f->Get32(obj));
1045           } else if (size == 4) {
1046             rec->AddU4(f->Get32(obj));
1047           } else {
1048             CHECK_EQ(size, 8U);
1049             rec->AddU8(f->Get64(obj));
1050           }
1051         }
1052 
1053         sclass = sclass->GetSuperClass();
1054       }
1055 
1056       // Patch the instance field length.
1057       rec->UpdateU4(size_patch_offset, rec->Size() - (size_patch_offset + 4));
1058     }
1059   }
1060 
1061   ++objects_in_segment_;
1062   return 0;
1063 }
1064 
VisitRoot(const mirror::Object * obj,const RootInfo & root_info)1065 void Hprof::VisitRoot(const mirror::Object* obj, const RootInfo& root_info) {
1066   static const HprofHeapTag xlate[] = {
1067     HPROF_ROOT_UNKNOWN,
1068     HPROF_ROOT_JNI_GLOBAL,
1069     HPROF_ROOT_JNI_LOCAL,
1070     HPROF_ROOT_JAVA_FRAME,
1071     HPROF_ROOT_NATIVE_STACK,
1072     HPROF_ROOT_STICKY_CLASS,
1073     HPROF_ROOT_THREAD_BLOCK,
1074     HPROF_ROOT_MONITOR_USED,
1075     HPROF_ROOT_THREAD_OBJECT,
1076     HPROF_ROOT_INTERNED_STRING,
1077     HPROF_ROOT_FINALIZING,
1078     HPROF_ROOT_DEBUGGER,
1079     HPROF_ROOT_REFERENCE_CLEANUP,
1080     HPROF_ROOT_VM_INTERNAL,
1081     HPROF_ROOT_JNI_MONITOR,
1082   };
1083   CHECK_LT(root_info.GetType(), sizeof(xlate) / sizeof(HprofHeapTag));
1084   if (obj == NULL) {
1085     return;
1086   }
1087   gc_scan_state_ = xlate[root_info.GetType()];
1088   gc_thread_serial_number_ = root_info.GetThreadId();
1089   MarkRootObject(obj, 0);
1090   gc_scan_state_ = 0;
1091   gc_thread_serial_number_ = 0;
1092 }
1093 
1094 // If "direct_to_ddms" is true, the other arguments are ignored, and data is
1095 // sent directly to DDMS.
1096 // If "fd" is >= 0, the output will be written to that file descriptor.
1097 // Otherwise, "filename" is used to create an output file.
DumpHeap(const char * filename,int fd,bool direct_to_ddms)1098 void DumpHeap(const char* filename, int fd, bool direct_to_ddms) {
1099   CHECK(filename != NULL);
1100 
1101   Runtime::Current()->GetThreadList()->SuspendAll();
1102   Hprof hprof(filename, fd, direct_to_ddms);
1103   hprof.Dump();
1104   Runtime::Current()->GetThreadList()->ResumeAll();
1105 }
1106 
1107 }  // namespace hprof
1108 
1109 }  // namespace art
1110