@@ -678,14 +678,29 @@ class DynamicSegment : public BlobSection {
678678
679679static const intptr_t kProgramTableSegmentSize = Elf::kPageSize ;
680680
681- Elf::Elf (Zone* zone, StreamingWriteStream* stream, Dwarf* dwarf)
681+ // Here, both VM and isolate will be compiled into a single snapshot.
682+ // In assembly generation, each serialized text section gets a separate
683+ // pointer into the BSS segment and BSS slots are created for each, since
684+ // we may not serialize both VM and isolate. Here, we always serialize both,
685+ // so make a BSS segment large enough for both, with the VM entries coming
686+ // first.
687+ static const intptr_t kBssIsolateOffset =
688+ BSS::kVmEntryCount * compiler::target::kWordSize ;
689+ static const intptr_t kBssSize =
690+ kBssIsolateOffset + BSS::kIsolateEntryCount * compiler::target::kWordSize ;
691+
692+ Elf::Elf (Zone* zone, StreamingWriteStream* stream, Type type, Dwarf* dwarf)
682693 : zone_(zone),
683694 unwrapped_stream_(stream),
695+ type_(type),
684696 dwarf_(dwarf),
697+ bss_(CreateBSS(zone, type, kBssSize )),
685698 shstrtab_(new (zone) StringTable(/* allocate=*/ false )),
686699 dynstrtab_(new (zone) StringTable(/* allocate=*/ true )),
687700 dynsym_(new (zone) SymbolTable(/* dynamic=*/ true )),
688701 memory_offset_(kProgramTableSegmentSize ) {
702+ // Separate debugging information should always have a Dwarf object.
703+ ASSERT (type_ == Type::Snapshot || dwarf_ != nullptr );
689704 // Assumed by various offset logic in this file.
690705 ASSERT_EQUAL (unwrapped_stream_->position (), 0 );
691706 // The first section in the section header table is always a reserved
@@ -702,6 +717,19 @@ Elf::Elf(Zone* zone, StreamingWriteStream* stream, Dwarf* dwarf)
702717 AddSection (symtab_, " .symtab" );
703718 symtab_->section_link = strtab_->section_index ();
704719 }
720+ // Note that the BSS segment must be the first user-defined segment because
721+ // it cannot be placed in between any two non-writable segments, due to a bug
722+ // in Jelly Bean's ELF loader. See also Elf::WriteProgramTable().
723+ //
724+ // We add it in all cases, even to the separate debugging information ELF,
725+ // to ensure that relocated addresses are consistent between ELF snapshots
726+ // and ELF separate debugging information.
727+ AddSection (bss_, " .bss" );
728+ AddSegmentSymbol (bss_, " _kDartBSSData" );
729+ }
730+
731+ uword Elf::BssStart (bool vm) const {
732+ return bss_->memory_offset () + (vm ? 0 : kBssIsolateOffset );
705733}
706734
707735void Elf::AddSection (Section* section, const char * name) {
@@ -734,11 +762,14 @@ intptr_t Elf::AddSegmentSymbol(const Section* section, const char* name) {
734762}
735763
736764intptr_t Elf::AddText (const char * name, const uint8_t * bytes, intptr_t size) {
737- Section* image = nullptr ;
738- if (bytes != nullptr ) {
739- image = new (zone_) ProgramBits (true , true , false , bytes, size);
740- } else {
765+ // When making a separate debugging info file for assembly, we don't have
766+ // the binary text segment contents.
767+ ASSERT (type_ == Type::DebugInfo || bytes != nullptr );
768+ Section* image;
769+ if (type_ == Type::DebugInfo) {
741770 image = new (zone_) NoBits (true , true , false , size);
771+ } else {
772+ image = new (zone_) ProgramBits (true , true , false , bytes, size);
742773 }
743774 AddSection (image, " .text" );
744775
@@ -776,28 +807,34 @@ bool Elf::FindStaticSymbol(const char* name,
776807 return FindSymbol (strtab_, symtab_, name, offset, size);
777808}
778809
779- intptr_t Elf::AddBSSData (const char * name, intptr_t size) {
780- // Ideally the BSS segment would take no space in the object, but Android's
781- // "strip" utility truncates the memory-size of our segments to their
782- // file-size.
783- //
784- // Therefore we must insert zero-filled pages for the BSS.
785- uint8_t * const bytes = zone_->Alloc <uint8_t >(size);
786- memset (bytes, 0 , size);
787-
788- ProgramBits* const image =
789- new (zone_) ProgramBits (true , false , true , bytes, size);
810+ Section* Elf::CreateBSS (Zone* zone, Type type, intptr_t size) {
811+ Section* image;
812+ if (type == Type::DebugInfo) {
813+ image = new (zone) NoBits (true , false , true , size);
814+ } else {
815+ // Ideally the BSS segment would take no space in the object, but Android's
816+ // "strip" utility truncates the memory-size of our segments to their
817+ // file-size.
818+ //
819+ // Therefore we must insert zero-filled pages for the BSS.
820+ uint8_t * const bytes = zone->Alloc <uint8_t >(size);
821+ memset (bytes, 0 , size);
822+ image = new (zone) ProgramBits (true , false , true , bytes, size);
823+ }
790824 static_assert (Image::kBssAlignment <= kPageSize ,
791825 " ELF .bss section is not aligned as expected by Image class" );
792826 ASSERT_EQUAL (image->alignment , kPageSize );
793- AddSection (image, " .bss" );
794-
795- return AddSegmentSymbol (image, name);
827+ return image;
796828}
797829
798830intptr_t Elf::AddROData (const char * name, const uint8_t * bytes, intptr_t size) {
799831 ASSERT (bytes != nullptr );
800- ProgramBits* image = new (zone_) ProgramBits (true , false , false , bytes, size);
832+ Section* image;
833+ if (type_ == Type::DebugInfo) {
834+ image = new (zone_) NoBits (true , false , false , size);
835+ } else {
836+ image = new (zone_) ProgramBits (true , false , false , bytes, size);
837+ }
801838 AddSection (image, " .rodata" );
802839
803840 return AddSegmentSymbol (image, name);
0 commit comments