From 35f92b0ad6deeefde5db5928b4b7b05e8d3cbae3 Mon Sep 17 00:00:00 2001 From: Konstantin Baladurin Date: Mon, 11 Sep 2017 20:23:16 +0300 Subject: [PATCH 29/29] Fix calculation of debuginfo's size. (#13899) Information about each type is dumped once but during debuginfo's size calculation it was taken into account several time. Due to it size of debuginfo section could be in several times bigger than needed that in some cases leaded to OOM. --- src/vm/gdbjit.cpp | 86 ++++++++++++++++++++++++++++++++++--------------------- src/vm/gdbjit.h | 9 ++++++ 2 files changed, 62 insertions(+), 33 deletions(-) diff --git a/src/vm/gdbjit.cpp b/src/vm/gdbjit.cpp index d21b4da..50f1bb2 100644 --- a/src/vm/gdbjit.cpp +++ b/src/vm/gdbjit.cpp @@ -939,11 +939,14 @@ void TypeDefInfo::DumpStrings(char *ptr, int &offset) void TypeDefInfo::DumpDebugInfo(char *ptr, int &offset) { - if (m_typedef_type_offset != 0) + if (m_is_visited && m_base_ptr == ptr) { return; } + m_base_ptr = ptr; + m_is_visited = true; + if (ptr != nullptr) { DebugInfoTypeDef buf; @@ -1014,10 +1017,14 @@ void PrimitiveTypeInfo::DumpStrings(char* ptr, int& offset) void PrimitiveTypeInfo::DumpDebugInfo(char *ptr, int &offset) { - if (m_type_offset != 0) + if (m_is_visited && m_base_ptr == ptr) { return; } + + m_base_ptr = ptr; + m_is_visited = true; + m_typedef_info->DumpDebugInfo(ptr, offset); if (ptr != nullptr) @@ -1031,13 +1038,12 @@ void PrimitiveTypeInfo::DumpDebugInfo(char *ptr, int &offset) memcpy(ptr + offset, &bufType, sizeof(DebugInfoType)); - m_type_offset = offset; + + // Replace offset from real type to typedef + m_type_offset = m_typedef_info->m_typedef_type_offset; } offset += sizeof(DebugInfoType); - // Replace offset from real type to typedef - if (ptr != nullptr) - m_type_offset = m_typedef_info->m_typedef_type_offset; } ClassTypeInfo::ClassTypeInfo(TypeHandle typeHandle, int num_members, FunctionMemberPtrArrayHolder &method) @@ -1106,7 +1112,21 @@ void TypeMember::DumpDebugInfo(char* ptr, int& offset) void TypeMember::DumpStaticDebugInfo(char* ptr, int& offset) { const int ptrSize = sizeof(TADDR); - int bufSize = 0; + const int valueTypeBufSize = ptrSize + 6; + const int refTypeBufSize = ptrSize + 2; + + bool isValueType = m_member_type->GetTypeHandle().GetSignatureCorElementType() == + ELEMENT_TYPE_VALUETYPE; + int bufSize; + if (isValueType) + { + bufSize = valueTypeBufSize; + } + else + { + bufSize = refTypeBufSize; + } + if (ptr != nullptr) { DebugInfoStaticMember memberEntry; @@ -1117,12 +1137,9 @@ void TypeMember::DumpStaticDebugInfo(char* ptr, int& offset) // for value type static fields compute address as: // addr = (*addr+sizeof(OBJECTREF)) - if (m_member_type->GetTypeHandle().GetSignatureCorElementType() == - ELEMENT_TYPE_VALUETYPE) + if (isValueType) { - bufSize = ptrSize + 6; - - char buf[ptrSize + 6] = {0}; + char buf[valueTypeBufSize] = {0}; buf[0] = ptrSize + 5; buf[1] = DW_OP_addr; @@ -1140,9 +1157,7 @@ void TypeMember::DumpStaticDebugInfo(char* ptr, int& offset) } else { - bufSize = ptrSize + 2; - - char buf[ptrSize + 2] = {0}; + char buf[refTypeBufSize] = {0}; buf[0] = ptrSize + 1; buf[1] = DW_OP_addr; @@ -1500,10 +1515,14 @@ void RefTypeInfo::DumpStrings(char* ptr, int& offset) void RefTypeInfo::DumpDebugInfo(char* ptr, int& offset) { - if (m_type_offset != 0) + if (m_is_visited && m_base_ptr == ptr) { return; } + + m_base_ptr = ptr; + m_is_visited = true; + m_type_offset = offset; offset += sizeof(DebugInfoRefType); m_value_type->DumpDebugInfo(ptr, offset); @@ -1523,10 +1542,14 @@ void RefTypeInfo::DumpDebugInfo(char* ptr, int& offset) void NamedRefTypeInfo::DumpDebugInfo(char* ptr, int& offset) { - if (m_type_offset != 0) + if (m_is_visited && m_base_ptr == ptr) { return; } + + m_base_ptr = ptr; + m_is_visited = true; + m_type_offset = offset; offset += sizeof(DebugInfoRefType) + sizeof(DebugInfoTypeDef); m_value_type->DumpDebugInfo(ptr, offset); @@ -1553,28 +1576,23 @@ void NamedRefTypeInfo::DumpDebugInfo(char* ptr, int& offset) void ClassTypeInfo::DumpDebugInfo(char* ptr, int& offset) { - if (m_type_offset != 0) + if (m_is_visited && m_base_ptr == ptr) { return; } + m_base_ptr = ptr; + m_is_visited = true; + if (m_parent != nullptr) { - if (m_parent->m_type_offset == 0) - { - m_parent->DumpDebugInfo(ptr, offset); - } - else if (RefTypeInfo* m_p = dynamic_cast(m_parent)) - { - if (m_p->m_value_type->m_type_offset == 0) - m_p->m_value_type->DumpDebugInfo(ptr, offset); - } + m_parent->DumpDebugInfo(ptr, offset); } // make sure that types of all members are dumped for (int i = 0; i < m_num_members; ++i) { - if (members[i].m_member_type->m_type_offset == 0 && members[i].m_member_type != this) + if (members[i].m_member_type != this) { members[i].m_member_type->DumpDebugInfo(ptr, offset); } @@ -1638,14 +1656,16 @@ void ClassTypeInfo::DumpDebugInfo(char* ptr, int& offset) void ArrayTypeInfo::DumpDebugInfo(char* ptr, int& offset) { - if (m_type_offset != 0) + if (m_is_visited && m_base_ptr == ptr) { return; } - if (m_elem_type->m_type_offset == 0) - { - m_elem_type->DumpDebugInfo(ptr, offset); - } + + m_base_ptr = ptr; + m_is_visited = true; + + m_elem_type->DumpDebugInfo(ptr, offset); + if (ptr != nullptr) { DebugInfoArrayType arrType; diff --git a/src/vm/gdbjit.h b/src/vm/gdbjit.h index ebd5a7a..d2843bb 100644 --- a/src/vm/gdbjit.h +++ b/src/vm/gdbjit.h @@ -119,12 +119,21 @@ struct SymbolsInfo class DwarfDumpable { public: + DwarfDumpable() : + m_base_ptr(nullptr), + m_is_visited(false) + { + } + // writes all string literals this type needs to ptr virtual void DumpStrings(char* ptr, int& offset) = 0; virtual void DumpDebugInfo(char* ptr, int& offset) = 0; virtual ~DwarfDumpable() {} + + char *m_base_ptr; + bool m_is_visited; }; class LocalsInfo -- 2.7.4