@@ -409,7 +409,7 @@ static bool segmentOverlapsSegment(const Segment &Child,
409
409
Parent.OriginalOffset + Parent.FileSize > Child.OriginalOffset ;
410
410
}
411
411
412
- static bool compareSegments (const Segment *A, const Segment *B) {
412
+ static bool compareSegmentsByOffset (const Segment *A, const Segment *B) {
413
413
// Any segment without a parent segment should come before a segment
414
414
// that has a parent segment.
415
415
if (A->OriginalOffset < B->OriginalOffset )
@@ -419,6 +419,14 @@ static bool compareSegments(const Segment *A, const Segment *B) {
419
419
return A->Index < B->Index ;
420
420
}
421
421
422
+ static bool compareSegmentsByPAddr (const Segment *A, const Segment *B) {
423
+ if (A->PAddr < B->PAddr )
424
+ return true ;
425
+ if (A->PAddr > B->PAddr )
426
+ return false ;
427
+ return A->Index < B->Index ;
428
+ }
429
+
422
430
template <class ELFT >
423
431
void Object<ELFT>::readProgramHeaders(const ELFFile<ELFT> &ElfFile) {
424
432
uint32_t Index = 0 ;
@@ -456,9 +464,9 @@ void Object<ELFT>::readProgramHeaders(const ELFFile<ELFT> &ElfFile) {
456
464
if (&Child != &Parent && segmentOverlapsSegment (*Child, *Parent)) {
457
465
// We want a canonical "most parental" segment but this requires
458
466
// inspecting the ParentSegment.
459
- if (compareSegments (Parent.get (), Child.get ()))
467
+ if (compareSegmentsByOffset (Parent.get (), Child.get ()))
460
468
if (Child->ParentSegment == nullptr ||
461
- compareSegments (Parent.get (), Child->ParentSegment )) {
469
+ compareSegmentsByOffset (Parent.get (), Child->ParentSegment )) {
462
470
Child->ParentSegment = Parent.get ();
463
471
}
464
472
}
@@ -784,7 +792,8 @@ static uint64_t alignToAddr(uint64_t Offset, uint64_t Addr, uint64_t Align) {
784
792
785
793
// Orders segments such that if x = y->ParentSegment then y comes before x.
786
794
static void OrderSegments (std::vector<Segment *> &Segments) {
787
- std::stable_sort (std::begin (Segments), std::end (Segments), compareSegments);
795
+ std::stable_sort (std::begin (Segments), std::end (Segments),
796
+ compareSegmentsByOffset);
788
797
}
789
798
790
799
// This function finds a consistent layout for a list of segments starting from
@@ -793,7 +802,7 @@ static void OrderSegments(std::vector<Segment *> &Segments) {
793
802
static uint64_t LayoutSegments (std::vector<Segment *> &Segments,
794
803
uint64_t Offset) {
795
804
assert (std::is_sorted (std::begin (Segments), std::end (Segments),
796
- compareSegments ));
805
+ compareSegmentsByOffset ));
797
806
// The only way a segment should move is if a section was between two
798
807
// segments and that section was removed. If that section isn't in a segment
799
808
// then it's acceptable, but not ideal, to simply move it to after the
@@ -947,14 +956,29 @@ template <class ELFT> void BinaryObject<ELFT>::finalize() {
947
956
OrderedSegments.push_back (Section->ParentSegment );
948
957
}
949
958
}
950
- OrderSegments (OrderedSegments);
959
+
960
+ // For binary output, we're going to use physical addresses instead of
961
+ // virtual addresses, since a binary output is used for cases like ROM
962
+ // loading and physical addresses are intended for ROM loading.
963
+ // However, if no segment has a physical address, we'll fallback to using
964
+ // virtual addresses for all.
965
+ if (std::all_of (std::begin (OrderedSegments), std::end (OrderedSegments),
966
+ [](const Segment *Segment) { return Segment->PAddr == 0 ; }))
967
+ for (const auto &Segment : OrderedSegments)
968
+ Segment->PAddr = Segment->VAddr ;
969
+
970
+ std::stable_sort (std::begin (OrderedSegments), std::end (OrderedSegments),
971
+ compareSegmentsByPAddr);
972
+
951
973
// Because we add a ParentSegment for each section we might have duplicate
952
974
// segments in OrderedSegments. If there were duplicates then LayoutSegments
953
975
// would do very strange things.
954
976
auto End =
955
977
std::unique (std::begin (OrderedSegments), std::end (OrderedSegments));
956
978
OrderedSegments.erase (End, std::end (OrderedSegments));
957
979
980
+ uint64_t Offset = 0 ;
981
+
958
982
// Modify the first segment so that there is no gap at the start. This allows
959
983
// our layout algorithm to proceed as expected while not out writing out the
960
984
// gap at the start.
@@ -963,19 +987,18 @@ template <class ELFT> void BinaryObject<ELFT>::finalize() {
963
987
auto Sec = Seg->firstSection ();
964
988
auto Diff = Sec->OriginalOffset - Seg->OriginalOffset ;
965
989
Seg->OriginalOffset += Diff;
966
- // The size needs to be shrunk as well
990
+ // The size needs to be shrunk as well.
967
991
Seg->FileSize -= Diff;
968
- Seg->MemSize -= Diff;
969
- // The VAddr needs to be adjusted so that the alignment is correct as well
970
- Seg->VAddr += Diff;
971
- Seg->PAddr = Seg->VAddr ;
972
- // We don't want this to be shifted by alignment so we need to set the
973
- // alignment to zero.
974
- Seg->Align = 0 ;
992
+ // The PAddr needs to be increased to remove the gap before the first
993
+ // section.
994
+ Seg->PAddr += Diff;
995
+ uint64_t LowestPAddr = Seg->PAddr ;
996
+ for (auto &Segment : OrderedSegments) {
997
+ Segment->Offset = Segment->PAddr - LowestPAddr;
998
+ Offset = std::max (Offset, Segment->Offset + Segment->FileSize );
999
+ }
975
1000
}
976
1001
977
- uint64_t Offset = LayoutSegments (OrderedSegments, 0 );
978
-
979
1002
// TODO: generalize LayoutSections to take a range. Pass a special range
980
1003
// constructed from an iterator that skips values for which a predicate does
981
1004
// not hold. Then pass such a range to LayoutSections instead of constructing
0 commit comments