Commit Graph

1548 Commits

Author SHA1 Message Date
Lang Hames
52298507e8 Back out r208257 while I investigate tester failures.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@208267 91177308-0d34-0410-b5e6-96231b3b80d8
2014-05-07 23:35:53 +00:00
Lang Hames
3186597423 [RuntimeDyld] Make RuntimeDyldImpl::resolveExternalSymbols preserve the
relocation entries it applies.

Prior to this patch, RuntimeDyldImpl::resolveExternalSymbols discarded
relocations for external symbols once they had been applied. This causes issues
if the client calls MCJIT::finalizeLoadedModules more than once, and updates the
location of any symbols in between (e.g. by calling MCJIT::mapSectionAddress).

No test case yet: None of our in-tree memory managers support moving sections
around. I'll have to hack up a dummy memory manager before I can write a unit
test.

Fixes <rdar://problem/16764378>



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@208257 91177308-0d34-0410-b5e6-96231b3b80d8
2014-05-07 22:34:08 +00:00
James Molloy
44ff92f64a [ARM64] Try and make the ELF MCJIT *slightly* less broken for ARM64.
A bunch of switch cases were missing, not just for ARM64 but also for
AArch64_BE. I've fixed all those, but there's zero testing as
ExecutionEngine tests are disabled when crosscompiling and I don't
have a native platform available to test on.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@207626 91177308-0d34-0410-b5e6-96231b3b80d8
2014-04-30 10:15:41 +00:00
Reid Kleckner
fc288c8339 Fix the build with MSVC 2013 by explicitly requesting llvm::make_unique
MSVC 2013 provides std::make_unique, which it finds with ADL when one of
the parameters is std::unique_ptr, leading to an ambiguous overload.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@207597 91177308-0d34-0410-b5e6-96231b3b80d8
2014-04-29 23:54:52 +00:00
David Blaikie
167cb010a4 Fix MSVC build broken by r207580
Seems MSVC wants to be able to codegen inline-definitions of virtual
functions even in TUs that don't define the key function - and it's well
within its rights to do so.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@207581 91177308-0d34-0410-b5e6-96231b3b80d8
2014-04-29 22:04:55 +00:00
David Blaikie
00121bb932 PR19553: Memory leak in RuntimeDyldELF::createObjectImageFromFile
This starts in MCJIT::getSymbolAddress where the
unique_ptr<object::Binary> is release()d and (after a cast) passed to a
single caller, MCJIT::addObjectFile.

addObjectFile calls RuntimeDyld::loadObject.
RuntimeDld::loadObject calls RuntimeDyldELF::createObjectFromFile

And the pointer is never owned at this point. I say this point, because
the alternative codepath, RuntimeDyldMachO::createObjectFile certainly
does take ownership, so this seemed like a good hint that this was a/the
right place to take ownership.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@207580 91177308-0d34-0410-b5e6-96231b3b80d8
2014-04-29 21:52:46 +00:00
Craig Topper
c34a25d59d [C++] Use 'nullptr'.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@207394 91177308-0d34-0410-b5e6-96231b3b80d8
2014-04-28 04:05:08 +00:00
Craig Topper
e703fcb975 [C++] Use 'nullptr'.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@207083 91177308-0d34-0410-b5e6-96231b3b80d8
2014-04-24 06:44:33 +00:00
Chandler Carruth
0d338a59bd [Modules] Fix potential ODR violations by sinking the DEBUG_TYPE
definition below all the header #include lines. This updates most of the
miscellaneous other lib/... directories. A few left though.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206845 91177308-0d34-0410-b5e6-96231b3b80d8
2014-04-22 03:04:17 +00:00
Jim Grosbach
59b626b938 Revert "[rtdyld,c++11] Range'ify symbol table walking."
Tentative revert for
http://lab.llvm.org:8011/builders/llvm-mips-linux/builds/8305.

This reverts commit c2a58efff07294fca724f89500538f2ddbcd12ff.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206773 91177308-0d34-0410-b5e6-96231b3b80d8
2014-04-21 19:23:59 +00:00
Jim Grosbach
72eedb3c1d [rtdyld,c++11] Range'ify symbol table walking.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206769 91177308-0d34-0410-b5e6-96231b3b80d8
2014-04-21 18:10:31 +00:00
Rafael Espindola
7426771280 Convert getFileOffset to getOffset and move it to its only user.
We normally don't drop functions from the C API's, but in this case I think we
can:

* The old implementation of getFileOffset was fairly broken
* The introduction of LLVMGetSymbolFileOffset was itself a C api breaking
  change as it removed LLVMGetSymbolOffset.
* It is an incredibly specialized use case. The only reason MCJIT needs it is
  because of its odd position of being a dynamic linker of .o files.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206750 91177308-0d34-0410-b5e6-96231b3b80d8
2014-04-21 13:45:32 +00:00
Lang Hames
c3097bfd9b [ExecutionEngine] Allow JIT clients to enable/disable module verification.
Previously module verification was always enabled, with no way to turn it off.
As of this commit, module verification is on by default in Debug builds, and off
by default in release builds. The default behaviour can be overridden by calling
setVerifyModules(bool) on the JIT instance (this works for both the old JIT, and
MCJIT).

<rdar://problem/16150008>



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206561 91177308-0d34-0410-b5e6-96231b3b80d8
2014-04-18 06:48:23 +00:00
Chandler Carruth
b9a99d4593 [Allocator] Finally, finish nuking the redundant code that led me here
by removing the MallocSlabAllocator entirely and just using
MallocAllocator directly. This makes all off these allocators expose and
utilize the same core interface.

The only ugly part of this is that it exposes the fact that the JIT
allocator has no real handling of alignment, any more than the malloc
allocator does. =/ It would be nice to fix both of these to support
alignments, and then to leverage that in the BumpPtrAllocator to do less
over allocation in order to manually align pointers. But, that's another
patch for another day. This patch has no functional impact, it just
removes the somewhat meaningless wrapper around MallocAllocator.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206267 91177308-0d34-0410-b5e6-96231b3b80d8
2014-04-15 09:44:09 +00:00
Craig Topper
0b6cb7104b [C++11] More 'nullptr' conversion. In some cases just using a boolean check instead of comparing to nullptr.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206252 91177308-0d34-0410-b5e6-96231b3b80d8
2014-04-15 06:32:26 +00:00
Kaelyn Takata
03e18573d4 Replace two calls to object::symbol_iterator::increment(), which had
been removed in r200442.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206196 91177308-0d34-0410-b5e6-96231b3b80d8
2014-04-14 17:26:50 +00:00
Chandler Carruth
17f9c2e35b [Allocator] Make the underlying allocator a template instead of an
abstract interface. The only user of this functionality is the JIT
memory manager and it is quite happy to have a custom type here. This
removes a virtual function call and a lot of unnecessary abstraction
from the common case where this is just a *very* thin vaneer around
a call to malloc.

Hopefully still no functionality changed here. =]

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206149 91177308-0d34-0410-b5e6-96231b3b80d8
2014-04-14 05:11:27 +00:00
Chandler Carruth
cb7ead25c2 [Allocator] Switch the BumpPtrAllocator to use a vector of pointers to
slabs rather than embedding a singly linked list in the slabs
themselves. This has a few advantages:

- Better utilization of the slab's memory by not wasting 16-bytes at the
  front.
- Simpler allocation strategy by not having a struct packed at the
  front.
- Avoids paging every allocated slab in just to traverse them for
  deallocating or dumping stats.

The latter is the really nice part. Folks have complained from time to
time bitterly that tearing down a BumpPtrAllocator, even if it doesn't
run any destructors, pages in all of the memory allocated. Now it won't.
=]

Also resolves a FIXME with the scaling of the slab sizes. The scaling
now disregards specially sized slabs for allocations larger than the
threshold.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206147 91177308-0d34-0410-b5e6-96231b3b80d8
2014-04-14 03:55:11 +00:00
NAKAMURA Takumi
accaa640cf LLVMBuild.txt: Add missing dependencies.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205962 91177308-0d34-0410-b5e6-96231b3b80d8
2014-04-10 11:16:47 +00:00
Elena Demikhovsky
ec8891fdde Changes in IntelJITEventListener - By Arch Robinson
- take->release: LLVM has moved to C++11.  MockWrapper became an instance of unique_ptr.

   - method symbol_iterator::increment disappeared recently, in this revision:

     r200442 | rafael | 2014-01-29 20:49:50 -0600 (Wed, 29 Jan 2014) | 9 lines

Simplify the handling of iterators in ObjectFile.

None of the object file formats reported error on iterator increment. In
retrospect, that is not too surprising: no object format stores symbols or
sections in a linked list or other structure that requires chasing pointers.
As a consequence, all error checking can be done on begin() and end().

This reduces the text segment of bin/llvm-readobj in my machine from 521233 to
518526 bytes.

My change mimics the change that the revision made to lib/DebugInfo/DWARFContext.cpp .

    - const_cast: Shut up a warning from gcc.

I ran unittests/ExecutionEngine/JIT/Debug+Asserts/JITTests to make sure it worked.

- Arch



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205689 91177308-0d34-0410-b5e6-96231b3b80d8
2014-04-06 11:08:33 +00:00
Rafael Espindola
67c46d286f Remove section_rel_empty. Just compare begin() and end() instead.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205577 91177308-0d34-0410-b5e6-96231b3b80d8
2014-04-03 22:42:22 +00:00
Chandler Carruth
368a977298 [Allocator] Lift the slab size and size threshold into template
parameters rather than runtime parameters.

There is only one user of these parameters and they are compile time for
that user. Making these compile time seems to better reflect their
intended usage as well.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205143 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-30 12:07:07 +00:00
Tim Northover
7b837d8c75 ARM64: initial backend import
This adds a second implementation of the AArch64 architecture to LLVM,
accessible in parallel via the "arm64" triple. The plan over the
coming weeks & months is to merge the two into a single backend,
during which time thorough code review should naturally occur.

Everything will be easier with the target in-tree though, hence this
commit.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205090 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-29 10:18:08 +00:00
Christian Pirker
1f072c36d0 Add ARM big endian Target (armeb, thumbeb)
Reviewed at http://llvm-reviews.chandlerc.com/D3095



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205007 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-28 14:35:30 +00:00
Chandler Carruth
ec90ab499d [cleanup] Hoist the initialization and constants for slab sizes to the
top of the default jit memory manager. This will allow them to be used
as template parameters rather than runtime parameters in a subsequent
commit.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204992 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-28 08:53:08 +00:00
Rafael Espindola
f165cf7ce8 Prevent alias from pointing to weak aliases.
This adds back r204781.

Original message:

Aliases are just another name for a position in a file. As such, the
regular symbol resolutions are not applied. For example, given

define void @my_func() {
  ret void
}
@my_alias = alias weak void ()* @my_func
@my_alias2 = alias void ()* @my_alias

We produce without this patch:

        .weak   my_alias
my_alias = my_func
        .globl  my_alias2
my_alias2 = my_alias

That is, in the resulting ELF file my_alias, my_func and my_alias are
just 3 names pointing to offset 0 of .text. That is *not* the
semantics of IR linking. For example, linking in a

@my_alias = alias void ()* @other_func

would require the strong my_alias to override the weak one and
my_alias2 would end up pointing to other_func.

There is no way to represent that with aliases being just another
name, so the best solution seems to be to just disallow it, converting
a miscompile into an error.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204934 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-27 15:26:56 +00:00
Juergen Ributzka
50c385683c [MCJIT] Check if there have been errors during RuntimeDyld execution.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204837 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-26 18:19:27 +00:00
Christian Pirker
a634d0a570 AArch64_BE Elf support for MC-JIT runtime dynamic linker
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204816 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-26 14:57:32 +00:00
Rafael Espindola
72db10a995 Revert "Prevent alias from pointing to weak aliases."
This reverts commit r204781.

I will follow up to with msan folks to see what is what they
were trying to do with aliases to weak aliases.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204784 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-26 06:14:40 +00:00
Rafael Espindola
33845aa8c4 Prevent alias from pointing to weak aliases.
Aliases are just another name for a position in a file. As such, the
regular symbol resolutions are not applied. For example, given

define void @my_func() {
  ret void
}
@my_alias = alias weak void ()* @my_func
@my_alias2 = alias void ()* @my_alias

We produce without this patch:

        .weak   my_alias
my_alias = my_func
        .globl  my_alias2
my_alias2 = my_alias

That is, in the resulting ELF file my_alias, my_func and my_alias are
just 3 names pointing to offset 0 of .text. That is *not* the
semantics of IR linking. For example, linking in a

@my_alias = alias void ()* @other_func

would require the strong my_alias to override the weak one and
my_alias2 would end up pointing to other_func.

There is no way to represent that with aliases being just another
name, so the best solution seems to be to just disallow it, converting
a miscompile into an error.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204781 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-26 04:48:47 +00:00
Juergen Ributzka
56db3a97cd [RuntimeDyld] Fix comment for previous commit (r204439)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204508 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-21 20:38:46 +00:00
Juergen Ributzka
b0e33fdcd0 [RuntimeDyld] clang-format files.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204507 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-21 20:28:42 +00:00
Juergen Ributzka
4923eea4f6 [RuntimeDyld] Allow processRelocationRef to process more than one relocation entry at a time.
Some targets require more than one relocation entry to perform a relocation.
This change allows processRelocationRef to process more than one relocation
entry at a time by passing the relocation iterator itself instead of just
the relocation entry.

Related to <rdar://problem/16199095>

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204439 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-21 07:26:41 +00:00
Lang Hames
20425d92df Add an option to MCJIT to have it forward all sections to the
RTDyldMemoryManager, regardless of whether it thinks they're "required for
execution".

Currently, RuntimeDyld only passes sections that are "required for execution"
to the RTDyldMemoryManager, and takes "required for execution" to mean exactly
"contains symbols or relocations". There are two problems with this:
(1) It can drop sections with anonymous data that is referenced by code.
(2) It leaves the JIT client no way to inspect interesting sections that aren't
    actually required to run the program (e.g dwarf sections).

A test case is still in the works.

Future work: We may want to replace this with a generic section filtering
mechanism, but that will require more consideration. For now, this flag at least
allows clients to volunteer to do the filtering themselves.

Fixes <rdar://problem/15177691>.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204398 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-20 21:06:46 +00:00
Alexey Samsonov
6f07b35b8f [C++11] Introduce SectionRef::relocations() to use range-based loops
Reviewers: rafael

Reviewed By: rafael

CC: llvm-commits

Differential Revision: http://llvm-reviews.chandlerc.com/D3077

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203927 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-14 14:22:49 +00:00
Lang Hames
303d39f1c4 Make GDBJITRegistrar thread safe. Patch by Jim Kearyn, with cleanup by
Ivan Puzyrevskiy.

Fixes PR15750. Thanks Jim and Ivan.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203853 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-13 21:25:37 +00:00
Ulrich Weigand
4f45d04c6f [ppc64] Patch in TOC restore code after all external function calls
When resolving a function call to an external routine, the dynamic
loader must patch the "nop" after the branch instruction to a load
that restores the TOC register.

Current code does that, but only with the *first* instance of a call
to any particular external routine, i.e. at the point where it also
allocates the call stub.  With subsequent calls to the same routine,
current code neglects to patch in the TOC restore code.  This is a
bug, and leads to corrupt TOC pointers in those cases.

Fixed by patching in restore code every time.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203580 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-11 15:26:27 +00:00
Lang Hames
f089b84699 Make createObjectImage and createObjectImageFromFile static methods on the
relevant subclasses of RuntimeDyldImpl. This allows construction of
RuntimeDyldImpl instances to be deferred until after the target architecture is
known.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203352 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-08 18:45:12 +00:00
Craig Topper
838cb749dc [C++11] Add 'override' keyword to virtual methods that override their base class.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203344 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-08 07:51:20 +00:00
Ahmed Charles
f4ccd11075 Replace OwningPtr<T> with std::unique_ptr<T>.
This compiles with no changes to clang/lld/lldb with MSVC and includes
overloads to various functions which are used by those projects and llvm
which have OwningPtr's as parameters. This should allow out of tree
projects some time to move. There are also no changes to libs/Target,
which should help out of tree targets have time to move, if necessary.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203083 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-06 05:51:42 +00:00
Chandler Carruth
67f6bf70d2 [Layering] Move InstVisitor.h into the IR library as it is pretty
obviously coupled to the IR.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203064 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-06 03:23:41 +00:00
Chandler Carruth
f4ec8bfaec [Layering] Move DebugInfo.h into the IR library where its implementation
already lives.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203046 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-06 00:46:21 +00:00
Ahmed Charles
1a6eca243f [C++11] Replace OwningPtr::take() with OwningPtr::release().
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202957 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-05 10:19:29 +00:00
Chandler Carruth
7225e27b4c [Modules] Move ValueMap to the IR library. While this class does not
directly care about the Value class (it is templated so that the key can
be any arbitrary Value subclass), it is in fact concretely tied to the
Value class through the ValueHandle's CallbackVH interface which relies
on the key type being some Value subclass to establish the value handle
chain.

Ironically, the unittest is already in the right library.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202824 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-04 11:26:31 +00:00
Chandler Carruth
eb3d76da81 [Modules] Move ValueHandle into the IR library where Value itself lives.
Move the test for this class into the IR unittests as well.

This uncovers that ValueMap too is in the IR library. Ironically, the
unittest for ValueMap is useless in the Support library (honestly, so
was the ValueHandle test) and so it already lives in the IR unittests.
Mmmm, tasty layering.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202821 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-04 11:17:44 +00:00
Chandler Carruth
4bbfbdf7d7 [Modules] Move CallSite into the IR library where it belogs. It is
abstracting between a CallInst and an InvokeInst, both of which are IR
concepts.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202816 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-04 11:01:28 +00:00
Chandler Carruth
bd7cba0d81 [Modules] Move GetElementPtrTypeIterator into the IR library. As its
name might indicate, it is an iterator over the types in an instruction
in the IR.... You see where this is going.

Another step of modularizing the support library.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202815 91177308-0d34-0410-b5e6-96231b3b80d8
2014-03-04 10:40:04 +00:00
Rafael Espindola
356deb5ecd Use DataLayout from the module when easily available.
Eventually DataLayoutPass should go away, but for now that is the only easy
way to get a DataLayout in some APIs. This patch only changes the ones that
have easy access to a Module.

One interesting issue with sometimes using DataLayoutPass and sometimes
fetching it from the Module is that we have to make sure they are equivalent.
We can get most of the way there by always constructing the pass with a Module.
In fact, the pass could be changed to point to an external DataLayout instead
of owning one to make this stricter.

Unfortunately, the C api passes a DataLayout, so it has to be up to the caller
to make sure the pass and the module are in sync.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202204 91177308-0d34-0410-b5e6-96231b3b80d8
2014-02-25 23:25:17 +00:00
Rafael Espindola
57edc9d4ff Make DataLayout a plain object, not a pass.
Instead, have a DataLayoutPass that holds one. This will allow parts of LLVM
don't don't handle passes to also use DataLayout.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202168 91177308-0d34-0410-b5e6-96231b3b80d8
2014-02-25 17:30:31 +00:00
Rafael Espindola
b4aaffffd3 move getNameWithPrefix and getSymbol to TargetMachine.
TargetLoweringBase is implemented in CodeGen, so before this patch we had
a dependency fom Target to CodeGen. This would show up as a link failure of
llvm-stress when building with -DBUILD_SHARED_LIBS=ON.

This fixes pr18900.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@201711 91177308-0d34-0410-b5e6-96231b3b80d8
2014-02-19 20:30:41 +00:00