[patch] fix Thumb text sections' flags under COFF/Windows

Hello everyone,

Here is attached a patch that fixes the flags of text sections when
compiling thumb code under Windows using clang. The patch has been made
against the svn commit r273084.

The main issue is that the "thumb" flag wasn't set for some of these
sections, making MSVC's link.exe fails to correctly relocate code
against the symbols inside these sections. link.exe could fail for
instance with the "fixup is not aligned for target 'XX'" error. If
linking doesn't fail, the relocation process goes wrong in the end and
invalid code is generated by the linker.

To reproduce the error, one can compile this file as a static library:

#include <stdio.h>

void test(const char* s)
{
  const void* ptr = &snprintf;
  printf("%s: %p\n", s, ptr);
}

and then create a dynamic library that links against this static library
(which calls the 'test' function). A visual studio project can be
provided for people interested.

As a side note, I fixed something I think is a potential bug here:

Index: lib/MC/MCObjectFileInfo.cpp

--- lib/MC/MCObjectFileInfo.cpp (revision 273084)
+++ lib/MC/MCObjectFileInfo.cpp (working copy)
@@ -595,7 +595,7 @@
                        COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE,
       SectionKind::getData());

- bool IsWoA = T.getArch() == Triple::arm || T.getArch() == Triple::thumb;
+ const bool IsThumb = T.getArch() == Triple::thumb;

   CommDirectiveSupportsAlignment = true;

@@ -606,7 +606,7 @@
       SectionKind::getBSS());
   TextSection = Ctx->getCOFFSection(
       ".text",
- (IsWoA ? COFF::IMAGE_SCN_MEM_16BIT : (COFF::SectionCharacteristics)0) |
+ (IsThumb ? COFF::IMAGE_SCN_MEM_16BIT : (COFF::SectionCharacteristics)0) |
           COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE |
           COFF::IMAGE_SCN_MEM_READ,
       SectionKind::getText());

Indeed, the "SCN_MEM_16BIT" flag (which indicate that the text sections
contain thumb code [1]) is set even if we are compiling non-thumb code.
I couldn't check this as thumb mode seems to be forced in
clang/lib/Driver/ToolChain.cpp, function ToolChain::ComputeLLVMTriple :

    // FIXME: this is invalid for WindowsCE
    if (getTriple().isOSWindows())
      ThumbDefault = true;
...
    if ((InputType != types::TY_PP_Asm && Args.hasFlag(options::OPT_mthumb,
         options::OPT_mno_thumb, ThumbDefault)) || IsMProfile) {
      if (IsBigEndian)
        ArchName = "thumbeb";
      else
        ArchName = "thumb";
    }

Commenting this and forcing the ARM mode by default will makes
clang/llvm complains that this isn't supported (I didn't dug further).

If more information are necessary, I'd be glad to provide them!
Thanks!

Regards,

[1] : in the official COFF documentation (TODO URL), this flag is set as
"reserved for future use". However, using the dumpbin.exe tool provided
with Visual Studio (with the /headers flag), it seems that this flag is
the one that set the section as containing thumb code.

thumb.patch (2.94 KB)

TODO URL:
https://msdn.microsoft.com/en-us/library/windows/hardware/gg463119.aspx

Sorry for the spam :slight_smile:

By the way, thanks to Kevin Szkudlapski who helped me figured this out!