@@ -697,8 +697,16 @@ size_t getSymbolSize ( COFF_HEADER_INFO *info )
697
697
}
698
698
}
699
699
700
+ // Constants which may be returned by getSymSectionNumber.
701
+ // See https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#section-number-values
702
+ #define PE_SECTION_UNDEFINED ((uint32_t) 0)
703
+ #define PE_SECTION_ABSOLUTE ((uint32_t) -1)
704
+ #define PE_SECTION_DEBUG ((uint32_t) -2)
705
+
706
+ // Returns either PE_SECTION_{UNDEFINED,ABSOLUTE,DEBUG} or the (one-based)
707
+ // section number of the given symbol.
700
708
__attribute__ ((always_inline )) inline
701
- int32_t getSymSectionNumber ( COFF_HEADER_INFO * info , COFF_symbol * sym )
709
+ uint32_t getSymSectionNumber ( COFF_HEADER_INFO * info , COFF_symbol * sym )
702
710
{
703
711
ASSERT (info );
704
712
ASSERT (sym );
@@ -707,7 +715,13 @@ int32_t getSymSectionNumber ( COFF_HEADER_INFO *info, COFF_symbol* sym )
707
715
case COFF_ANON_BIG_OBJ :
708
716
return sym -> ex .SectionNumber ;
709
717
default :
710
- return sym -> og .SectionNumber ;
718
+ // Take care to only sign-extend reserved values; see #22941.
719
+ switch (sym -> og .SectionNumber ) {
720
+ case IMAGE_SYM_UNDEFINED : return PE_SECTION_UNDEFINED ;
721
+ case IMAGE_SYM_ABSOLUTE : return PE_SECTION_ABSOLUTE ;
722
+ case IMAGE_SYM_DEBUG : return PE_SECTION_DEBUG ;
723
+ default : return (uint16_t ) sym -> og .SectionNumber ;
724
+ }
711
725
}
712
726
}
713
727
@@ -1652,7 +1666,7 @@ ocGetNames_PEi386 ( ObjectCode* oc )
1652
1666
StgWord globalBssSize = 0 ;
1653
1667
for (unsigned int i = 0 ; i < info -> numberOfSymbols ; i ++ ) {
1654
1668
COFF_symbol * sym = & oc -> info -> symbols [i ];
1655
- if (getSymSectionNumber (info , sym ) == IMAGE_SYM_UNDEFINED
1669
+ if (getSymSectionNumber (info , sym ) == PE_SECTION_UNDEFINED
1656
1670
&& getSymValue (info , sym ) > 0
1657
1671
&& getSymStorageClass (info , sym ) != IMAGE_SYM_CLASS_SECTION ) {
1658
1672
globalBssSize += getSymValue (info , sym );
@@ -1685,21 +1699,39 @@ ocGetNames_PEi386 ( ObjectCode* oc )
1685
1699
for (unsigned int i = 0 ; i < (uint32_t )oc -> n_symbols ; i ++ ) {
1686
1700
COFF_symbol * sym = & oc -> info -> symbols [i ];
1687
1701
1688
- int32_t secNumber = getSymSectionNumber (info , sym );
1689
1702
uint32_t symValue = getSymValue (info , sym );
1690
1703
uint8_t symStorageClass = getSymStorageClass (info , sym );
1691
-
1692
1704
SymbolAddr * addr = NULL ;
1693
1705
bool isWeak = false;
1694
1706
SymbolName * sname = get_sym_name (getSymShortName (info , sym ), oc );
1695
- Section * section = secNumber > 0 ? & oc -> sections [secNumber - 1 ] : NULL ;
1707
+
1708
+ uint32_t secNumber = getSymSectionNumber (info , sym );
1709
+ Section * section ;
1710
+ switch (secNumber ) {
1711
+ case PE_SECTION_UNDEFINED :
1712
+ // N.B. This may be a weak symbol
1713
+ section = NULL ;
1714
+ break ;
1715
+ case PE_SECTION_ABSOLUTE :
1716
+ IF_DEBUG (linker , debugBelch ("symbol %s is ABSOLUTE, skipping...\n" , sname ));
1717
+ i += getSymNumberOfAuxSymbols (info , sym );
1718
+ continue ;
1719
+ case PE_SECTION_DEBUG :
1720
+ IF_DEBUG (linker , debugBelch ("symbol %s is DEBUG, skipping...\n" , sname ));
1721
+ i += getSymNumberOfAuxSymbols (info , sym );
1722
+ continue ;
1723
+ default :
1724
+ CHECK (secNumber < (uint32_t ) oc -> n_sections );
1725
+ section = & oc -> sections [secNumber - 1 ];
1726
+ }
1696
1727
1697
1728
SymType type ;
1698
1729
switch (getSymType (oc -> info -> ch_info , sym )) {
1699
1730
case 0x00 : type = SYM_TYPE_DATA ; break ;
1700
1731
case 0x20 : type = SYM_TYPE_CODE ; break ;
1701
1732
default :
1702
- debugBelch ("Invalid symbol type: 0x%x\n" , getSymType (oc -> info -> ch_info , sym ));
1733
+ debugBelch ("Symbol %s has invalid type 0x%x\n" ,
1734
+ sname , getSymType (oc -> info -> ch_info , sym ));
1703
1735
return 1 ;
1704
1736
}
1705
1737
@@ -1730,8 +1762,18 @@ ocGetNames_PEi386 ( ObjectCode* oc )
1730
1762
CHECK (symValue == 0 );
1731
1763
COFF_symbol_aux_weak_external * aux = (COFF_symbol_aux_weak_external * ) (sym + 1 );
1732
1764
COFF_symbol * targetSym = & oc -> info -> symbols [aux -> TagIndex ];
1733
- int32_t targetSecNumber = getSymSectionNumber (info , targetSym );
1734
- Section * targetSection = targetSecNumber > 0 ? & oc -> sections [targetSecNumber - 1 ] : NULL ;
1765
+
1766
+ uint32_t targetSecNumber = getSymSectionNumber (info , targetSym );
1767
+ Section * targetSection ;
1768
+ switch (targetSecNumber ) {
1769
+ case PE_SECTION_UNDEFINED :
1770
+ case PE_SECTION_ABSOLUTE :
1771
+ case PE_SECTION_DEBUG :
1772
+ targetSection = NULL ;
1773
+ break ;
1774
+ default :
1775
+ targetSection = & oc -> sections [targetSecNumber - 1 ];
1776
+ }
1735
1777
addr = (SymbolAddr * ) ((size_t ) targetSection -> start + getSymValue (info , targetSym ));
1736
1778
}
1737
1779
else if ( secNumber == IMAGE_SYM_UNDEFINED && symValue > 0 ) {
@@ -1850,6 +1892,9 @@ ocGetNames_PEi386 ( ObjectCode* oc )
1850
1892
return false;
1851
1893
1852
1894
break ;
1895
+ } else if (secNumber == PE_SECTION_UNDEFINED ) {
1896
+ IF_DEBUG (linker , debugBelch ("symbol %s is UNDEFINED, skipping...\n" , sname ));
1897
+ i += getSymNumberOfAuxSymbols (info , sym );
1853
1898
}
1854
1899
1855
1900
if ((addr != NULL || isWeak )
@@ -1976,7 +2021,19 @@ ocResolve_PEi386 ( ObjectCode* oc )
1976
2021
debugBelch ("'\n" ));
1977
2022
1978
2023
if (getSymStorageClass (info , sym ) == IMAGE_SYM_CLASS_STATIC ) {
1979
- Section section = oc -> sections [getSymSectionNumber (info , sym )- 1 ];
2024
+ uint32_t sect_n = getSymSectionNumber (info , sym );
2025
+ switch (sect_n ) {
2026
+ case PE_SECTION_UNDEFINED :
2027
+ case PE_SECTION_ABSOLUTE :
2028
+ case PE_SECTION_DEBUG :
2029
+ errorBelch (" | %" PATH_FMT ": symbol `%s' has invalid section number %02x" ,
2030
+ oc -> fileName , symbol , sect_n );
2031
+ return false;
2032
+ default :
2033
+ break ;
2034
+ }
2035
+ CHECK (sect_n < (uint32_t ) oc -> n_sections );
2036
+ Section section = oc -> sections [sect_n - 1 ];
1980
2037
S = ((size_t )(section .start ))
1981
2038
+ ((size_t )(getSymValue (info , sym )));
1982
2039
} else {
0 commit comments