|
42 | 42 |
|
43 | 43 | import java.io.BufferedReader;
|
44 | 44 | import java.io.File;
|
| 45 | +import java.io.FileInputStream; |
45 | 46 | import java.io.IOException;
|
| 47 | +import java.io.InputStream; |
46 | 48 | import java.lang.ProcessBuilder.Redirect;
|
| 49 | +import java.nio.ByteBuffer; |
| 50 | +import java.nio.ByteOrder; |
47 | 51 | import java.nio.file.Files;
|
48 | 52 | import java.nio.file.Path;
|
49 | 53 | import java.nio.file.Paths;
|
|
57 | 61 | import jline.internal.InputStreamReader;
|
58 | 62 |
|
59 | 63 | public class GraalPythonLD extends GraalPythonCompiler {
|
60 |
| - private static final String LLVM_IR_BITCODE = "llvm-ir-bitcode"; |
61 | 64 | private static final String LLVM_NM = "llvm-nm";
|
| 65 | + private static final long BC_MAGIC_WORD = 0xdec04342L; // 'BC' c0de |
| 66 | + private static final long WRAPPER_MAGIC_WORD = 0x0B17C0DEL; |
| 67 | + |
62 | 68 | private static List<String> linkPrefix = Arrays.asList(new String[]{
|
63 | 69 | "llvm-link",
|
64 | 70 | "-o",
|
@@ -107,16 +113,11 @@ private void parseOptions(String[] args) {
|
107 | 113 | } else if (arg.startsWith("-l")) {
|
108 | 114 | List<String> bcFiles = searchLib(libraryDirs, arg.substring(2));
|
109 | 115 | for (String bcFile : bcFiles) {
|
110 |
| - try { |
111 |
| - String contentType = Files.probeContentType(Paths.get(bcFile)); |
112 |
| - if (contentType != null && contentType.contains(LLVM_IR_BITCODE)) { |
113 |
| - logV("library input:", bcFile); |
114 |
| - addFile(bcFile); |
115 |
| - } else { |
116 |
| - droppedArgs.add(bcFile + "(dropped as library input)"); |
117 |
| - } |
118 |
| - } catch (IOException e) { |
119 |
| - throw new RuntimeException(e); |
| 116 | + if (probeContentType(Paths.get(bcFile))) { |
| 117 | + logV("library input:", bcFile); |
| 118 | + addFile(bcFile); |
| 119 | + } else { |
| 120 | + droppedArgs.add(bcFile + "(dropped as library input)"); |
120 | 121 | }
|
121 | 122 | }
|
122 | 123 | } else {
|
@@ -246,8 +247,7 @@ private Collection<? extends String> arMembers(String path) throws IOException,
|
246 | 247 | // seems ok to emulate this at least for the very common case of ar archives with symbol
|
247 | 248 | // definitions that overlap what's defined in explicitly include .o files
|
248 | 249 | outer: for (String f : members) {
|
249 |
| - String contentType = Files.probeContentType(Paths.get(f)); |
250 |
| - if (contentType != null && contentType.contains(LLVM_IR_BITCODE)) { |
| 250 | + if (probeContentType(Paths.get(f))) { |
251 | 251 | HashSet<String> definedFuncs = new HashSet<>();
|
252 | 252 | HashSet<String> definedGlobals = new HashSet<>();
|
253 | 253 |
|
@@ -310,4 +310,24 @@ private void launchLD() {
|
310 | 310 | ldArgs.addAll(fileInputs);
|
311 | 311 | exec(ldArgs);
|
312 | 312 | }
|
| 313 | + |
| 314 | + private static boolean probeContentType(Path path) { |
| 315 | + long magicWord = readMagicWord(path); |
| 316 | + if (magicWord == BC_MAGIC_WORD || magicWord == WRAPPER_MAGIC_WORD) { |
| 317 | + return true; |
| 318 | + } |
| 319 | + return false; |
| 320 | + } |
| 321 | + |
| 322 | + private static long readMagicWord(Path path) { |
| 323 | + try (InputStream is = new FileInputStream(path.toString())) { |
| 324 | + byte[] buffer = new byte[4]; |
| 325 | + if (is.read(buffer) != buffer.length) { |
| 326 | + return 0; |
| 327 | + } |
| 328 | + return Integer.toUnsignedLong(ByteBuffer.wrap(buffer).order(ByteOrder.nativeOrder()).getInt()); |
| 329 | + } catch (IOException e) { |
| 330 | + return 0; |
| 331 | + } |
| 332 | + } |
313 | 333 | }
|
0 commit comments