Skip to content

Commit 15e6e8c

Browse files
committed
rustc: Stop using LLVMGetSectionName
The recent pull request to remove libc from libstd has hit a wall in compiling on windows, and I've been trying to investigate on the try bots as to why (it compiles locally just fine). To the best of my knowledge, the LLVM section iterator is behaving badly when iterating over the sections of the libc DLL. Upon investigating the LLVMGetSectionName function in LLVM, I discovered that this function doesn't always return a null-terminated string. It returns the data pointer of a StringRef instance (LLVM's equivalent of &str essentially), but it has no method of returning the length of the name of the section. This commit modifies the section iteration when loading libraries to invoke a custom LLVMRustGetSectionName which will correctly return both the length and the data pointer. I have not yet verified that this will fix landing liblibc, as it will require a snapshot before doing a full test. Regardless, this is a worrisome situation regarding the LLVM API, and should likely be fixed anyway.
1 parent 6f1c06d commit 15e6e8c

File tree

3 files changed

+33
-5
lines changed

3 files changed

+33
-5
lines changed

src/librustc/lib/llvm.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1438,8 +1438,6 @@ pub mod llvm {
14381438
-> Bool;
14391439
/** Moves the section iterator to point to the next section. */
14401440
pub fn LLVMMoveToNextSection(SI: SectionIteratorRef);
1441-
/** Returns the current section name. */
1442-
pub fn LLVMGetSectionName(SI: SectionIteratorRef) -> *c_char;
14431441
/** Returns the current section size. */
14441442
pub fn LLVMGetSectionSize(SI: SectionIteratorRef) -> c_ulonglong;
14451443
/** Returns the current section contents as a string buffer. */
@@ -1784,6 +1782,9 @@ pub mod llvm {
17841782

17851783
pub fn LLVMRustSetDLLExportStorageClass(V: ValueRef);
17861784
pub fn LLVMVersionMinor() -> c_int;
1785+
1786+
pub fn LLVMRustGetSectionName(SI: SectionIteratorRef,
1787+
data: *mut *c_char) -> c_int;
17871788
}
17881789
}
17891790

src/librustc/metadata/loader.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,10 @@ use std::cast;
2929
use std::cmp;
3030
use std::io;
3131
use std::os::consts::{macos, freebsd, linux, android, win32};
32+
use std::ptr;
3233
use std::rc::Rc;
33-
use std::str;
3434
use std::slice;
35+
use std::str;
3536

3637
use collections::{HashMap, HashSet};
3738
use flate;
@@ -439,8 +440,9 @@ fn get_metadata_section_imp(os: Os, filename: &Path) -> Result<MetadataBlob, ~st
439440
};
440441
let si = mk_section_iter(of.llof);
441442
while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
442-
let name_buf = llvm::LLVMGetSectionName(si.llsi);
443-
let name = str::raw::from_c_str(name_buf);
443+
let mut name_buf = ptr::null();
444+
let name_len = llvm::LLVMRustGetSectionName(si.llsi, &mut name_buf);
445+
let name = str::raw::from_buf_len(name_buf as *u8, name_len as uint);
444446
debug!("get_metadata_section: name {}", name);
445447
if read_meta_section_name(os) == name {
446448
let cbuf = llvm::LLVMGetSectionContents(si.llsi);

src/rustllvm/RustWrapper.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include "rustllvm.h"
1212
#include "llvm/Object/Archive.h"
13+
#include "llvm/Object/ObjectFile.h"
1314

1415
//===----------------------------------------------------------------------===
1516
//
@@ -679,3 +680,27 @@ extern "C" int
679680
LLVMVersionMinor() {
680681
return LLVM_VERSION_MINOR;
681682
}
683+
684+
// Note that the two following functions look quite similar to the
685+
// LLVMGetSectionName function. Sadly, it appears that this function only
686+
// returns a char* pointer, which isn't guaranteed to be null-terminated. The
687+
// function provided by LLVM doesn't return the length, so we've created our own
688+
// function which returns the length as well as the data pointer.
689+
//
690+
// For an example of this not returning a null terminated string, see
691+
// lib/Object/COFFObjectFile.cpp in the getSectionName function. One of the
692+
// branches explicitly creates a StringRef without a null terminator, and then
693+
// that's returned.
694+
695+
inline section_iterator *unwrap(LLVMSectionIteratorRef SI) {
696+
return reinterpret_cast<section_iterator*>(SI);
697+
}
698+
699+
extern "C" int
700+
LLVMRustGetSectionName(LLVMSectionIteratorRef SI, const char **ptr) {
701+
StringRef ret;
702+
if (error_code ec = (*unwrap(SI))->getName(ret))
703+
report_fatal_error(ec.message());
704+
*ptr = ret.data();
705+
return ret.size();
706+
}

0 commit comments

Comments
 (0)